基於UDP的伺服器端和客戶端

2021-07-12 07:05:46 字數 3398 閱讀 3927

前面的文章中我們給出了幾個tcp的例子,對於udp而言,只要能理解前面的內容,實現並非難事。udp不像tcp,無需在連線狀態下交換資料,因此基於udp的伺服器端和客戶端也無需經過連線過程。也就是說,不必呼叫 listen() 和 accept() 函式。udp中只有建立套接字的過程和資料交換的過程。tcp中,套接字是一對一的關係。如要向10個客戶端提供服務,那麼除了負責監聽的套接字外,還需要建立10套接字。但在udp中,不管是伺服器端還是客戶端都只需要1個套接字。之前解釋udp原理的時候舉了郵寄包裹的例子,負責郵寄包裹的快遞公司可以比喻為udp套接字,只要有1個快遞公司,就可以通過它向任意位址郵寄包裹。同樣,只需1個udp套接字就可以向任意主機傳送資料。建立好tcp套接字後,傳輸資料時無需再新增位址資訊,因為tcp套接字將保持與對方套接字的連線。換言之,tcp套接字知道目標位址資訊。但udp套接字不會保持連線狀態,每次傳輸資料都要新增目標位址資訊,這相當於在郵寄包裹前填寫收件人位址。

傳送資料使用 sendto() 函式:

ssize_t

sendto

(int sock,

void

*buf,

size_t

nbytes,

int flags,

struct

sockaddr

*to,

socklen_t

addrlen);

//linux

intsendto

(socket

sock,

const

char

*buf,

int nbytes,

int flags,

const

struct

sockadr

*to,

int addrlen);

//windows

linux和windows下的 sendto() 函式類似,下面是詳細引數說明:

udp 傳送函式 sendto() 與tcp傳送函式 write()/send() 的最大區別在於,sendto() 函式需要向他傳遞目標位址資訊。

接收資料使用 recvfrom() 函式:

ssize_t

recvfrom

(int sock,

void

*buf,

size_t

nbytes,

int flags,

struct

sockadr

*from,

socklen_t

*addrlen);

//linux

intrecvfrom

(socket

sock,

char

*buf,

int nbytes,

int flags,

const

struct

sockaddr

*from,

int*addrlen);

//windows

由於udp資料的傳送端不不定,所以 recvfrom() 函式定義為可接收傳送端資訊的形式,具體引數如下:下面結合之前的內容實現回聲客戶端。需要注意的是,udp不同於tcp,不存在請求連線和受理過程,因此在某種意義上無法明確區分伺服器端和客戶端,只是因為其提供服務而稱為伺服器端,希望各位讀者不要誤解。

下面給出windows下的**,linux與此類似,不再贅述。

伺服器端 server.cpp:

#include

#include

#pragma

comment

(lib,

"ws2_32.lib"

)//載入 ws2_32.dll

#define buf_size 100

intmain

()closesocket

(sock);

wsacleanup

();return0;

}

**說明:

1) 第12行**在建立套接字時,向 socket() 第二個引數傳遞 sock_dgram,以指明使用udp協議。

2) 第18行**中使用htonl(inaddr_any)來自動獲取ip位址。

利用常數 inaddr_any 自動獲取ip位址有乙個明顯的好處,就是當軟體安裝到其他伺服器或者伺服器ip位址改變時,不用再更改原始碼重新編譯,也不用在啟動軟體時手動輸入。而且,如果一台計算機中已分配多個ip位址(例如路由器),那麼只要埠號一致,就可以從不同的ip位址接收資料。所以,伺服器中優先考慮使用inaddr_any;而客戶端中除非帶有一部分伺服器功能,否則不會採用。

客戶端 client.cpp:

#include

#include

#pragma

comment

(lib,

"ws2_32.lib"

)//載入 ws2_32.dll

#define buf_size 100

intmain();

printf

("input a string: "

);gets

(buffer);

sendto

(sock, buffer,

strlen

(buffer),0,

(struct

sockaddr

*)&servaddr,

sizeof

(servaddr));

int strlen =

recvfrom

(sock, buffer, buf_size,0,

&fromaddr,

&addrlen);

buffer[strlen]=0

;printf

("message form server: %s\n"

, buffer);

}closesocket

(sock);

wsacleanup

();return0;

}

先執行 server,再執行 client,client 輸出結果為:

input a string: c語言中文網

message form server: c語言中文網

input a string: c.biancheng.net founded in 2012

message form server: c.biancheng.net founded in 2012

input a string:

從**中可以看出,server.cpp 中沒有使用 listen() 函式,client.cpp 中也沒有使用 connect() 函式,因為 udp 不需要連線。

基於UDP的伺服器端和客戶端

前面的文章中我們給出了幾個 tcp 的例子,對於 udp 而言,只要能理解前面的內容,實現並非難事。udp 不像 tcp,無需在連線狀態下交換資料,因此基於 udp 的伺服器端和客戶端也無需經過連線過程。也就是說,不必呼叫 listen 和 accept 函式。udp 中只有建立套接字的過程和資料交...

基於UDP的伺服器端和客戶端

前面我們想過了tcp方式的,現在我們說下udp套接字的方式,內容較少,但是很實用。下面通過信件說明udp的工作原理,這是講解udp時使用的傳統示例,它與udp特性完全相符。寄信前應先在信封上填好寄信人和收信人的位址,之後貼上郵票放進郵筒即可。當然,信件的特點使我們無法確認對方是否收到。另外,郵寄過程...

6 1 基於UDP的伺服器端 客戶端

1.udp套接字原理 可靠性方面來說,tcp的確比udp好,但是udp的結構比tcp簡潔,不會傳送類似ack應答訊息,也不會有seq序號,效能有時比tcp高出很多。同時區分tcp和udp的重要標誌是流控制 tcp的生命在於流控制。圖中,ip的作用是讓離開主機b的udp資料報準確傳送到主機 但是最終交...