UDP套接字 C實現

2021-10-03 20:54:06 字數 4014 閱讀 4879

介紹套接字

套接字是網際網路使用者層的介面,可以實現不同終端間的資料傳遞;在c中套接字的各種函式和資料結構分布在很多庫里,在此不詳細說每乙個函式在哪個庫中,使用到的程式中使用到套接字的函式都包括在以下庫中

#include

#include

#include

#include

#include

執行環境

執行環境為windows子系統ubuntu 18.04 lts

程式作用

程式分為兩個部分:客戶端程式和伺服器程式

客戶端程式把字串yyyyyyyyyy傳送給伺服器,然後接受伺服器傳送的時間並顯示

伺服器程式接受客戶端傳送的資料.顯示客戶端的ip位址,埠號,客戶端傳來的字串.最終把系統時間傳回客戶端.

客戶端程式

下面分塊介紹客戶端程式

首先宣告巢狀字,實際上巢狀字就是乙個int型資料,使用socket函式初始化即可.下面socket函式傳遞的第乙個引數為ipv4協議(pf_inet);第二個引數為無連線通訊(sock_dgram);第三個引數為udp協議(ipproto_udp)

// 建立套接字,引數:ipv4協議,連線型別,udp協議

int client_fd =

socket

(pf_inet, sock_dgram, ipproto_udp)

;

struct sockaddr_in 

;

伺服器位址只是用了三個元素,協議簇初始為af_inet,表示ipv4;sin_addr.s_addr這個元素可以看到是ip位址,但是在這裡要把用字串表示的ip位址通過inet_addr()轉成需要的格式;最後乙個埠號賦值為12000

:這個結構體是繼承struct sockaddr的結構體,兩者大小一樣,一般要使用的時候需要將struct sockaddr_in *轉成struct sockaddr *

// 伺服器的位址

struct sockaddr_in server_addr;

int addr_size =

sizeof

(struct sockaddr)

;// 清空伺服器位址

memset

(&server_addr,

0, addr_size)

;// 位址為ip位址

server_addr.sin_family = af_inet;

//伺服器ip位址,127.0.0.1是本機,也就是傳給自己電腦

server_addr.sin_addr.s_addr=

inet_addr

("127.0.0.1");

//伺服器端口號,這個可以隨意1024-65535

server_addr.sin_port=

htons

(12000

);

接下來開始對伺服器傳送字串buf;這裡用到函式sendto();第乙個引數是客戶端的套接字client_fd;第二個引數是要傳送的字串buf;第三個引數是緩衝區大小,即字串的最大長度;第四個引數不用管,傳0;第五個引數傳遞伺服器的位址,但是這裡要轉成基類的指標;第六個引數傳遞位址結構的大小,這個在之前已經計算得出為addr_size,這裡也可寫為sizeof(struct sockaddr)

// 初始化要傳送的字串

memset

(buf,

'y',10)

;printf

("sending: '%s'\n"

,buf)

;// 傳送資料,引數如下

// 客戶套接字,字串,字串最大長度,0,伺服器位址,位址大小

sendto

(client_fd, buf, maxbuf,0,

(struct sockaddr *

)&server_addr, addr_size)

;

最後要接受從伺服器傳來的資訊,這裡使用recvfrom()函式,revcfrom函式和sendto差不多,要注意的是它的返回值.當成功接收時返回值為讀取到字串的長度,在程式中儲存cc裡面,之後的程式用到cc給字串加上結束符』\0』.具體程式如下:

int cc =

recvfrom

(client_fd, buf, maxbuf,0,

(struct sockaddr *

)&server_addr,

&addr_size)

; buf[cc]

='\0'

;printf

("%s"

, buf)

;

整個客戶端完整**:

#include

#include

#include

#include

#include

#include

#define maxbuf 20000

intmain()

伺服器程式

伺服器程式和客戶端很像,只需要討論其中的一些差別即可

伺服器端程式要建立套接字並繫結到伺服器的位址上,繫結的函式使用bind函式;這個函式的第乙個引數就是伺服器的套接字;第二個引數是伺服器的位址**成基類);第三個引數是位址大大小

// 建立套接字並繫結

int server_sock =

socket

(af_inet, sock_dgram, ipproto_udp)

;// 清空伺服器位址

memset

(&server_addr,

0, addr_size)

;// 位址為ip位址

server_addr.sin_family = af_inet;

// inaddr_any表示可以接受任意的ip位址發來的訊息

server_addr.sin_addr.s_addr = inaddr_any;

// 埠

server_addr.sin_port =

htons

(12000);

// 繫結套接字,和位址

bind

(server_sock,

(struct sockaddr *

)&server_addr,

sizeof

(struct sockaddr)

);

伺服器程式還要接受多個客戶程式的請求,因此在這裡設定了乙個死迴圈,每次伺服器程式接受客戶資訊並且傳送時間之後,都等待另乙個客戶的資訊,程式最終需要在命令列中輸入ctrl+c結束,迴圈的過程如下:

printf

("the server is ready\n-----------------------\n");

while(1

)

總客戶程式**如下:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define maxbuf 20000

intmain

(int argc,

char

**ar**)

return0;

}

執行結果

先啟動伺服器程式,可以看到如下介面

接下來啟動客戶端程式,有如下介面;在這裡可以看到客戶程式從伺服器程式返回的資料中獲得了時間

再次檢視伺服器端結果如下:

可以看到伺服器程式已經取出ip位址,埠號和客戶傳來的字串

感覺c語言編寫套接字真的很多細節要注意,只是很粗略講一下都是好幾千字,下次將tcp套接字估計更長,可能考慮以後寫一些python的**這樣看起來比較方便

UDP套接字程式設計

與面向連線的協議相比,面向無連線協議極為不同。其中乙個重要的不同點就是客戶端與伺服器之間不必建立連線。對於udp套接字程式設計而言,伺服器建立套接字後,呼叫bind 函式將套接字與準備接收資料的介面繫結在一起。和tcp程式設計不同的是,應用程式不必呼叫listen 和accept 函式等待客戶端的連...

UDP套接字程式設計

udp是使用者資料報協議,與tcp協議一樣,在網路中處理資料報,是一種無連線的傳輸層協議,具有不可靠性,udp有不提供資料報分組 組裝和不能對資料報進行排序的缺點,也就是說,當報文傳送之後,是無法得知其是否安全完整到達的。基於udp的客戶端伺服器 伺服器 include include includ...

關於udp套接字

setsockopt so reuseaddr 同一終端先後兩次執行udp server,該選項無影響。兩個 或多個 終端同時執行udp server,配置該選項時,僅第乙個終端執行成功 不配置時,所有終端均可成功執行udp server。udp客戶端呼叫connect 實現 不發起三次握手 僅將服...