VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 2525|回复: 2

[分享] 基于UDP的select函数用法

[复制链接]
51_avatar_middle
online_admins 发表于 2017-4-18 17:40:02 | 显示全部楼层 |阅读模式
Server端:
  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放入要<a href="http://lib.csdn.net/base/softwaretest" class='replace_word' title="软件测试知识库" target='_blank' style='color:#df3434; font-weight:bold;'>测试</a>的描述符集中
  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. }
复制代码


Client端:
  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);        // 向服务器发送数据&#160;
复制代码




上一篇:UDP select模型无法接受到数据
下一篇:关于C语音语法*和&amp;的使用小总结
98_avatar_middle
在线会员 发表于 2017-4-19 08:28:41 | 显示全部楼层
学习了
好教材
37_avatar_middle
在线会员 发表于 2017-11-9 11:49:33 | 显示全部楼层
有下載包嗎,感謝分享唷
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2019-3-26 23:36

Powered by Discuz! X3.4

© 2009-2019 cctry.com

快速回复 返回顶部 返回列表