分享

基于UDP的select函数用法

 心不留意外尘 2017-07-17

http://blog.csdn.net/FeeLang/article/details/4983317

2009

  1. /************SERVER**************/  
  2. #include <winsock2.h>  
  3. #include <stdio.h>  
  4. #define PORT_A  11111  
  5. #define PORT_B  22222  
  6. void main(int argc, char **argv)  
  7. {  
  8.     WSADATA wsaData; // 套接口信息数据  
  9.     SOCKET socka;   // 套接口a  
  10.     SOCKET sockb;   // 套接口b  
  11.       
  12.     int nPortA = PORT_A;  
  13.     int nPortB = PORT_B;  
  14.     fd_set rfd;     // 读描述符集  
  15.     timeval timeout;    // 定时变量  
  16.     sockaddr_in addr; // 告诉sock 应该在什么地方licence  
  17.     char recv_buf[1024];    // 接收缓冲区  
  18.       
  19.     int nRecLen; // 客户端地址长度!!!!!!  
  20.       
  21.     sockaddr_in cli;    // 客户端地址  
  22.     int nRet; // select返回值  
  23.     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)  
  24.     {  
  25.         printf("failed to laod winsock!/n");  
  26.         return;  
  27.     }  
  28.     socka = socket(AF_INET, SOCK_DGRAM, 0); // 创建数据报socka  
  29.     if (socka == INVALID_SOCKET)  
  30.     {  
  31.         printf("socket()/n");  
  32.         return;  
  33.     }  
  34.     sockb = socket(AF_INET, SOCK_DGRAM, 0); // 创建数据报sockb  
  35.     if (sockb == INVALID_SOCKET)  
  36.     {  
  37.         printf("socket()/n");  
  38.         return;  
  39.     }  
  40.     memset(&addr, 0, sizeof(addr));  
  41.       
  42.     addr.sin_family = AF_INET;   // IP协议  
  43.     addr.sin_port = htons(nPortA); // 端口  
  44.     addr.sin_addr.s_addr = htonl(INADDR_ANY); // 在本机的所有ip上开始监听  
  45.     if (bind(socka, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)// bind socka  
  46.     {  
  47.         printf("bind()/n");  
  48.         return;  
  49.     }  
  50.       
  51.     memset(&addr, 0, sizeof(addr));  
  52.     addr.sin_family = AF_INET;   // IP协议  
  53.     addr.sin_port = htons(nPortB); // 端口  
  54.     addr.sin_addr.s_addr = htonl(INADDR_ANY); // 在本机的所有ip上开始监听  
  55.       
  56.     if (bind(sockb, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) // bind sockb  
  57.     {  
  58.         printf("bind()/n");  
  59.         return;  
  60.     }  
  61.     // 设置超时时间为6s  
  62.     timeout.tv_sec = 6;   
  63.     timeout.tv_usec = 0;  
  64.       
  65.     memset(recv_buf, 0, sizeof(recv_buf)); // 清空接收缓冲区  
  66.     while (true)  
  67.     {  
  68.         FD_ZERO(&rfd); // 在使用之前总是要清空  
  69.           
  70.         // 开始使用select  
  71.         FD_SET(socka, &rfd); // 把socka放入要测试的描述符集中  
  72.         FD_SET(sockb, &rfd); // 把sockb放入要测试的描述符集中  
  73.           
  74.         nRet = select(0, &rfd, NULL, NULL, &timeout);// 检测是否有套接口是否可读  
  75.         if (nRet == SOCKET_ERROR)     
  76.         {  
  77.             printf("select()/n");  
  78.             return;  
  79.         }  
  80.         else if (nRet == 0) // 超时  
  81.         {  
  82.             printf("timeout/n");  
  83.             closesocket(socka);  
  84.             closesocket(sockb);  
  85.             break;  
  86.         }  
  87.         else    // 检测到有套接口可读  
  88.         {  
  89.             if (FD_ISSET(socka, &rfd))  // socka可读  
  90.             {  
  91.                 nRecLen = sizeof(cli);  
  92.                 int nRecEcho = recvfrom(socka, recv_buf, sizeof(recv_buf), 0, (sockaddr*)&cli, &nRecLen);  
  93.                 if (nRecEcho == INVALID_SOCKET)  
  94.                 {  
  95.                     printf("recvfrom()/n");  
  96.                     break;  
  97.                 }  
  98.                 printf("data to port 11111: %s/n", recv_buf);  
  99.             }  
  100.             if (FD_ISSET(sockb, &rfd)) // sockb 可读  
  101.             {  
  102.                 nRecLen = sizeof(cli);  
  103.                 int nRecEcho = recvfrom(sockb, recv_buf, sizeof(recv_buf), 0, (sockaddr*)&cli, &nRecLen);  
  104.                 if (nRecEcho == INVALID_SOCKET)  
  105.                 {  
  106.                     printf("recvfrom()/n");  
  107.                     break;  
  108.                 }  
  109.                 printf("data to port 22222: %s/n", recv_buf);  
  110.             }  
  111.         }  
  112.     }  
  113.     WSACleanup();  
  114. }  

  1. /************CLIENT*************/  
  2. #include <winsock2.h>  
  3. #include <stdio.h>  
  4. #include <stdlib.h>  
  5. #define SERVER_PORT_A 11111     // 服务器端口A  
  6. #define SERVER_PORT_B 22222     // 服务器端口B  
  7. typedef struct tagSERVER    // 服务器  
  8. {  
  9.     char* ip;   // ip地址  
  10.     int nPort;  // 端口号  
  11. } SERVER, *PSERVER;   
  12. int SendData(SOCKET s, char *ip, int nPort, char *pData); // 发送数据到IP:nPort  
  13. int main(int argc, char **argv)  
  14. {  
  15.     int i;  
  16.     WSADATA wsaData;        // socket数据  
  17.     SOCKET sClient;         // 客户端套接口  
  18.     char send_buf[] = "hello! I am LiangFei whoes SNO=06060734";    // 发送的数据内容  
  19.     int nSend; // 发送数据后的返回值  
  20.     // 服务器  
  21.     SERVER sers[] = {   {"127.0.0.1", SERVER_PORT_A},   
  22.                         {"127.0.0.1", SERVER_PORT_B} };  
  23.     int nSerCount = sizeof(sers) / sizeof(sers[0]); // 服务器个数  
  24.     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)  // 启动socket  
  25.     {  
  26.         printf("failed to start up socket!/n");  
  27.         return 0;  
  28.     }  
  29.       
  30.     // 建立客户端数据包套接口  
  31.     sClient = socket(AF_INET, SOCK_DGRAM, 0);  
  32.     if (sClient == INVALID_SOCKET)  
  33.     {  
  34.         printf("socket()/n");  
  35.         return 0;  
  36.     }  
  37.     for (i = 0; i < nSerCount; i++)  
  38.     {  
  39.         nSend = SendData(sClient, sers[i].ip, sers[i].nPort, send_buf); // 发送数据  
  40.         if (nSend == 0) // 发送失败  
  41.         {  
  42.             return 0;  
  43.         }  
  44.         else if (nSend == SOCKET_ERROR) // 套接口出错  
  45.         {  
  46.             printf("sendto()/n");  
  47.             return 0;  
  48.         }  
  49.     }  
  50.     closesocket(sClient);   // 关闭套接口  
  51.     WSACleanup(); // 卸载winsock  
  52.     return 0;  
  53. }  
  54. int SendData(SOCKET s, char *ip, int nPort, char *pData)  
  55. {  
  56.     sockaddr_in ser;    // 服务器端地址     
  57.     ser.sin_family = AF_INET;   // IP协议  
  58.     ser.sin_port = htons(nPort);    // 端口号  
  59.     ser.sin_addr.s_addr = inet_addr(ip);    // IP地址  
  60.     int nLen = sizeof(ser); // 服务器地址长度  
  61.       
  62.     return sendto(s, pData, strlen(pData) + 1, 0, (sockaddr*)&ser, nLen);   // 向服务器发送数据   

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多