網絡編程-UDP echo server


1. UDP簡介 

  UDP 和TCP 的區別包括 1. 面向字節流和面向報文 2. TCP必須要建立連接后才能進行數據交換,但是UDP則並沒有連接的建立和釋放過程。面向字節流說明,tcp報文段(segment)是沒有邊界的,當服務器發送多個報文段到客戶端時,客戶端可能會把着多個報文段合並成一個報文段進行接收。但是對於UDP來說,數據是通過報文段進行傳輸的。

  如果說TCP協議可以用打電話去比喻,那么UDP協議可以用郵箱來形容。用郵箱傳遞信息時,雖然有丟失的可能性。但是用戶1發送的信件和用戶2接受的信件肯定是相同的。

2. 用UDP編寫echo server

  使用UDP,我們只需要修改一下socket函數的參數就OK了。

int client_sock = socket(PF_INET, SOCK_DGRAM, 0);

  然后就是創建兩個表示客戶端和服務端地址的sockaddr_in結構,其中serv_addr的各個字段需要我們自己填充。但是client_addr的各個字段是通過recvfrom通過指針進行自動填充。

struct sockaddr_in serv_addr, client_addr;

  填充serv_addr的各個字段:

 serv_addr.sin_family = AF_INET;
 serv_addr.sin_addr.s_addr = INADDR_ANY;
 serv_addr.sin_port = htons(8080);

   下來使用bind函數將套接字和服務器地址進行綁定。

 if (bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
     err_exit("bind error");
 }

  數據傳輸方面使用recv族和sendto進行數據傳輸,這里值得注意的是只有sendto中的sockaddr_in結構是需要手動填充的,sendto中的地址表示要發送的目標地址。recvfrom中的是獲取數據的源地址。下圖是echo服務器的交互流程。

      

 

3. 地址長度所遇到的一個坑

   在寫echo服務器中遇到一個問題,服務器端在運行過程中總是會出現如下錯誤:
  在stackoverflow看了下知道了應該是sockaddr的問題。出問題的代碼就是下面這一行。問題就在client_addr這塊。
int sLen = sendto(serv_sock, buffer, rLen, MSG_CONFIRM,
    (struct sockaddr *)&client_addr, recv_addr_len);

  client_addr是通過服務端調用recvfrom獲取的,我心想這也不用我手動填啊,怎么就又錯了。又反復看了書上的代碼,確定地址的獲取方式沒有錯,通過打印我發現地址確實有問題,端口和地址都不對。在網上搜了下 udp echo server的代碼,用可以正常運行的代碼和我的代碼細細比對,終於發現了問題所在。問題就出在地址長度的初始化上,我一直以為recvfrom中的地址長度是值-返回模式,但是實際上這個值也是要在recvfrom中起作用的。如果這個值不正確,client_addr的值也是錯誤的,導致服務器無法正常的把數據發送到客戶端。就醬。。。

socklen_t recv_addr_len = sizeof(client_addr); //正確的初始化方式
//socklen_t recv_addr_len;                       //錯誤的初始化方式
int rLen = recvfrom(serv_sock, buffer, MAX_LEN, MSG_WAITALL,
                    (struct sockaddr *)&client_addr, &recv_addr_len);

4. 參考

[3]  TCP/IP網絡編程

 
 
 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM