Win32 UDP Socket通信学习

学习内容,参见《Windows网络编程》第7章 Winsock基础

 

与TCP流式协议不同,UDP为数据报协议。

 

服务端接受数据,客户端发送数据。

UDP服务端流程

  • Socket或WSASocket建立套接字,用SOCK_DGRAM标志。
  • bind绑定到IP地址和端口。
  • recvfrom/WSARecvFrom接受数据。

 

UDP客户端流程

UDP客户端有两种方式,一种为无连接,一种为创建虚拟连接。

方式一 无连接

  • Socket或WSASocket建立套接字,用SOCK_DGRAM标志。
  • 设置服务器地址和端口。
  • sento/WSASendTo发送数据。

方式二 建立虚拟连接

  • Socket或WSASocket建立套接字,用SOCK_DGRAM标志。
  • 设置服务器地址和端口。
  • connect连接服务端。
  • 调用send发送数据。

 

使用windows的Winsock 2编程,需要进行工程配置。

  • 工程右键Properties->ConfigurationProperties->Linker->Input->Additional Dependencies中添加ws2_32.lib。
  • Demo代码采用Multi-Byte方式,设置Properties->ConfigurationProperties->General->Character Set为Use Multi-Byte Character Set。

备注:所有关系到收发数据的缓冲都属于简单的char类型,这些函数没有Unicode版本。当字符集为Unicode时,需要进行字符串转换。

 

服务端源码,UDPServer.cpp。

[cpp]  view plain copy
  1. // UDPServer.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <WinSock2.h>  
  6. #include <stdio.h>  
  7. #include <stdlib.h>  
  8.   
  9. #define DEFAULT_PORT 5150  
  10. #define DEFAULT_COUNT 5  
  11. #define DEFAULT_BUFFER_LENGTH 4096  
  12.   
  13. int iPort = DEFAULT_PORT;  
  14. DWORD dwCount = DEFAULT_COUNT;  
  15. DWORD dwLength = DEFAULT_BUFFER_LENGTH;  
  16. BOOL bInterface = FALSE;  
  17.   
  18. char szIterface[32];  
  19.   
  20. //Print usage information and exit  
  21. void usage()  
  22. {  
  23.     printf("usage:sender[-p:int][-i:IP][-n:x][-b:x]\n\n");  
  24.     printf("      -p:int  Local port\n");  
  25.     printf("      -i:IP    Local IP address to listen on\n");  
  26.     printf("      -n:x    Number of times to send message\n");  
  27.     printf("      -b:x    Size of buffer to send \n\n");  
  28.   
  29.     ExitProcess(1);  
  30. }  
  31.   
  32. //ValidateArgs  
  33. void ValidateArgs(int argc, _TCHAR** argv)  
  34. {  
  35.     for (int i = 1; i < argc; i++)  
  36.     {  
  37.         if ((argv[i][0] == _T('-') || (argv[i][0] == _T('/'))))  
  38.         {  
  39.             switch (tolower(argv[i][1]))  
  40.             {  
  41.             case _T('p'):  
  42.                 if (_tcslen(argv[i]) > 3)  
  43.                 {  
  44.                     iPort = _ttoi(&argv[i][3]);  
  45.                 }  
  46.                 break;  
  47.             case _T('n'):  
  48.                 //Number of times to receive message  
  49.                 if (_tcslen(argv[i]) > 3)  
  50.                 {  
  51.                     dwCount = _ttol(&argv[i][3]);  
  52.                 }  
  53.                 break;  
  54.             case _T('b'):  
  55.                 //Buffer size  
  56.                 if (_tcslen(argv[i]) > 3)  
  57.                 {  
  58.                     dwLength = _ttol(&argv[i][3]);  
  59.                 }  
  60.                 break;  
  61.             case _T('i'):  
  62.                 //Interface to receive datagrams on  
  63.                 if (_tcslen(argv[i]) > 3)  
  64.                 {  
  65.                     bInterface = TRUE;  
  66.                     _tcscpy_s(szIterface, &argv[i][3]);  
  67.                 }  
  68.                 break;  
  69.             default:  
  70.                 usage();  
  71.                 break;  
  72.             }  
  73.         }  
  74.     }  
  75. }  
  76.   
  77. int _tmain(int argc, _TCHAR* argv[])  
  78. {  
  79.     //Parse arguments and load winsock  
  80.     ValidateArgs(argc, argv);  
  81.   
  82.     WSADATA wsd;  
  83.     if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)  
  84.     {  
  85.         printf("WSAStartup failed!\n");  
  86.         return 1;  
  87.     }  
  88.   
  89.     //Create the socket, and bind it to a local interface and port  
  90.     SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);  
  91.     if (s == INVALID_SOCKET)  
  92.     {  
  93.         printf("socket() failed:%d\n", WSAGetLastError());  
  94.         return 1;  
  95.     }  
  96.   
  97.     SOCKADDR_IN local;  
  98.     local.sin_family = AF_INET;  
  99.     local.sin_port = htons((short)iPort);  
  100.     if (bInterface)  
  101.     {  
  102.         local.sin_addr.s_addr = inet_addr(szIterface);  
  103.     }  
  104.     else  
  105.     {  
  106.         local.sin_addr.s_addr = htonl(INADDR_ANY);  
  107.     }  
  108.   
  109.     if (bind(s, (SOCKADDR*)&local, sizeof(local)) == SOCKET_ERROR)  
  110.     {  
  111.         printf("bind() failed:%d\n", WSAGetLastError());  
  112.         return 1;  
  113.     }  
  114.   
  115.     //Allocate the receive buffer  
  116.     char* recvbuf = (char*)GlobalAlloc(GMEM_FIXED, dwLength);  
  117.     if (!recvbuf)  
  118.     {  
  119.         printf("GlobalAlloc() failed:%d\n", GetLastError());  
  120.         return 1;  
  121.     }  
  122.   
  123.     //Read the datagrams  
  124.     SOCKADDR_IN sender;  
  125.     for (int i = 0; i < (int)dwCount; i++)  
  126.     {  
  127.         int nSenderSize = sizeof(sender);  
  128.         int ret = recvfrom(s, recvbuf, dwLength, 0,  
  129.             (SOCKADDR*)&sender, &nSenderSize);  
  130.         if (ret == SOCKET_ERROR)  
  131.         {  
  132.             printf("recvfrom() failed:%d\n", WSAGetLastError());  
  133.             break;  
  134.         }  
  135.         else if (ret == 0)  
  136.         {  
  137.             break;  
  138.         }  
  139.         else  
  140.         {  
  141.             recvbuf[ret] = _T('\0');  
  142.             printf("[%s] sent me:'%s'\n",  
  143.                 inet_ntoa(sender.sin_addr), recvbuf);  
  144.         }  
  145.     }  
  146.     closesocket(s);  
  147.   
  148.     GlobalFree(recvbuf);  
  149.     WSACleanup();  
  150.     return 0;  
  151. }  

客户端源码,UDPClient.cpp。

[cpp]  view plain copy
  1. // UDPClient.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <WinSock2.h>  
  6. #include <stdio.h>  
  7. #include <stdlib.h>  
  8.   
  9. #define DEFAULT_PORT 5150  
  10. #define DEFAULT_COUNT 25  
  11. #define DEFAULT_CHAR 'a'  
  12. #define DEFAULT_BUFFER_LENGTH 32  
  13.   
  14. BOOL bConnect = FALSE;  
  15. int iPort = DEFAULT_PORT;  
  16. char cChar = DEFAULT_CHAR;  
  17. DWORD dwCount = DEFAULT_COUNT;  
  18. DWORD dwLength = DEFAULT_BUFFER_LENGTH;  
  19. char szRecipient[128];  
  20.   
  21. //Print usage information and exit  
  22. void usage()  
  23. {  
  24.     printf("usage:sender[-p:int][-r:IP][-c][-n:x][-b:x][-d:c]\n\n");  
  25.     printf("      -p:int    Remote port\n");  
  26.     printf("      -r:IP     Recipient's IP address or host name\n");  
  27.     printf("      -c         Connect to remote IP first\n");  
  28.     printf("      -n:x     Number of times to send message\n");  
  29.     printf("      -b:x     Size of buffer to send\n");  
  30.     printf("      -d:c     Character to fill buffer with\n\n");  
  31.     ExitProcess(1);  
  32. }  
  33.   
  34. //Parse the command line arguments, and set some global flags to  
  35. //indicate what actions to perform  
  36. void ValidateArgs(int argc, _TCHAR** argv)  
  37. {  
  38.     for (int i = 1; i < argc; i++)  
  39.     {  
  40.         if ((argv[i][0] == _T('-') || (argv[i][0] == _T('/'))))  
  41.         {  
  42.             switch (tolower(argv[i][1]))  
  43.             {  
  44.             case _T('p'):  
  45.                 //Remote port  
  46.                 if (_tcslen(argv[i]) > 3)  
  47.                 {  
  48.                     iPort = _ttoi(&argv[i][3]);  
  49.                 }  
  50.                 break;  
  51.             case _T('r'):  
  52.                 //Recipient's IP addr  
  53.                 if (_tcslen(argv[i]) > 3)  
  54.                 {  
  55.                     _tcscpy_s(szRecipient, &argv[i][3]);  
  56.                 }  
  57.                 break;  
  58.             case _T('c'):  
  59.                 //Connect to recipient's IP addr  
  60.                 bConnect = TRUE;  
  61.                 break;  
  62.             case _T('n'):  
  63.                 if (_tcslen(argv[i]) > 3)  
  64.                 {  
  65.                     dwCount = _ttol(&argv[i][3]);  
  66.                 }  
  67.                 break;  
  68.             case _T('b'):  
  69.                 if (_tcslen(argv[i]) > 3)  
  70.                 {  
  71.                     dwLength = _ttol(&argv[i][3]);  
  72.                 }  
  73.                 break;  
  74.             case _T('d'):  
  75.                 cChar = argv[i][3];  
  76.                 break;  
  77.             default:  
  78.                 usage();  
  79.                 break;  
  80.             }  
  81.         }  
  82.     }  
  83. }  
  84.   
  85. int _tmain(int argc, _TCHAR* argv[])  
  86. {  
  87.     ValidateArgs(argc, argv);  
  88.   
  89.     WSADATA wsd;  
  90.     if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)  
  91.     {  
  92.         printf("WSAStartup failed!\n");  
  93.         return 1;  
  94.     }  
  95.   
  96.     //Crate the socket  
  97.     SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);  
  98.     if (s == INVALID_SOCKET)  
  99.     {  
  100.         printf("socket() failed:%d\n", WSAGetLastError());  
  101.         return 1;  
  102.     }  
  103.   
  104.     //Resolve the recipient's IP address or host name  
  105.     SOCKADDR_IN recipient;  
  106.     recipient.sin_family = AF_INET;  
  107.     recipient.sin_port = htons((short)iPort);  
  108.   
  109.     int nServerLen = (int)_tcslen(szRecipient);  
  110.     if (0 == nServerLen)  
  111.     {  
  112.         struct hostent* host = gethostbyname(szRecipient);  
  113.         if (host == NULL)  
  114.         {  
  115.             printf("gethostbyname() failed:%d\n", WSAGetLastError());  
  116.             WSACleanup();  
  117.             return 1;  
  118.         }  
  119.   
  120.         CopyMemory(&recipient.sin_addr, host->h_addr_list[0], host->h_length);  
  121.     }  
  122.     else  
  123.     {  
  124.         recipient.sin_addr.s_addr = inet_addr(szRecipient);  
  125.     }  
  126.   
  127.     //Allocate the send buffer  
  128.     char* sendbuf = (char*)GlobalAlloc(GMEM_FIXED, dwLength);  
  129.     if (!sendbuf)  
  130.     {  
  131.         printf("GlobalAlloc() failed:%d\n", GetLastError());  
  132.         return 1;  
  133.     }  
  134.     memset(sendbuf, cChar, dwLength);  
  135.   
  136.     if (bConnect)  
  137.     {  
  138.         //If the connect option is set, "connect" to the recipient  
  139.         //and send the data with the send() fuction  
  140.   
  141.         if (connect(s, (SOCKADDR*)&recipient,  
  142.             sizeof(recipient)) == SOCKET_ERROR)  
  143.         {  
  144.             printf("connect() failed:%d\n", WSAGetLastError());  
  145.             GlobalFree(sendbuf);  
  146.             WSACleanup();  
  147.             return 1;  
  148.         }  
  149.   
  150.         for (int i = 0; i < (int)dwCount; i++)  
  151.         {  
  152.             int ret = send(s, sendbuf, dwLength, 0);  
  153.             if (ret == SOCKET_ERROR)  
  154.             {  
  155.                 printf("send() failed:%d\n", WSAGetLastError());  
  156.                 break;  
  157.             }  
  158.             else if (ret == 0)  
  159.             {  
  160.                 break;  
  161.             }  
  162.         }  
  163.     }  
  164.     else  
  165.     {  
  166.         //Otherwise, use the sendto() function  
  167.         for (int i = 0; i < (int)dwCount; i++)  
  168.         {  
  169.             int ret = sendto(s, sendbuf, dwLength, 0,  
  170.                 (SOCKADDR*)&recipient, sizeof(recipient));  
  171.             if (ret == SOCKET_ERROR)  
  172.             {  
  173.                 printf("send() failed:%d\n", WSAGetLastError());  
  174.                 break;  
  175.             }  
  176.             else if (ret == 0)  
  177.             {  
  178.                 break;  
  179.             }  
  180.         }  
  181.     }  
  182.   
  183.     closesocket(s);  
  184.     GlobalFree(sendbuf);  
  185.     WSACleanup();  
  186.     return 0;  
  187. }  

http://blog.csdn.net/segen_jaa/article/details/7565689


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值