前记:select模型主要用于解决tcp通信中,每次处理一个独立的客户都要单独的开线程,这样会导致客户连接数很大时,线程数也会很多。而使用select就会将线程缩减至2个,一个主线程用于接收Accept客户端的连接,另外一个子线程用于监听已经连接上来的客户端是否有信号状态,如果有信号则进行相应的消息处理。

服务端:

#include "stdafx.h"
#include <stdio.h>
#include <WinSock2.h>//必须放在windows.h前面
#include <Windows.h>
#include <stdlib.h>
#pragma comment(lib, "ws2_32.lib")fd_set g_fdClientSock;
int clientNum = 0;DWORD WINAPI ListenThreadProc(LPARAM lparam)
{fd_set fdRead;FD_ZERO(&fdRead);int nRet = 0;char *recvBuffer = (char*)malloc(1024);if (!recvBuffer){return -1;}memset(recvBuffer, 0, 1024);while (TRUE){fdRead = g_fdClientSock;timeval vt;vt.tv_sec = 0;vt.tv_usec = 0;nRet = select(0, &fdRead, 0,0,&vt);//会阻塞检查集合中所有socket是否有信号if (nRet != SOCKET_ERROR){for (int i=0; i<g_fdClientSock.fd_count; i++){if (FD_ISSET(g_fdClientSock.fd_array[i], &fdRead)){memset(recvBuffer, 0, 1024);nRet = recv(g_fdClientSock.fd_array[i], recvBuffer, 1024, 0);if (nRet >0){//todo:printf("接收到数据:%s", recvBuffer);send(g_fdClientSock.fd_array[i], recvBuffer, strlen(recvBuffer), 0);}else//如果接收失败,则从集合中清除响应socket,并把客户端数量减1{closesocket(g_fdClientSock.fd_array[i]);clientNum--;FD_CLR(g_fdClientSock.fd_array[i], &g_fdClientSock);}}}}}if (recvBuffer){free(recvBuffer);recvBuffer=nullptr;}return 0;
}void main()
{int port = 5099;WSADATA wsaData;if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){printf("Failed to load Winsock");return;}//创建用于监听的套接字  AF_INET:IPV4版本SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);if (sockSrv == INVALID_SOCKET){return;}//地址绑定-告诉操作系统是在哪一个地址及端口SOCKADDR_IN addrSrv;addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(port); //1024以上的端口号,htons本地转换为网络数据addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//电脑上所有的网络ipint retVal = bind(sockSrv, (LPSOCKADDR)&addrSrv, sizeof(SOCKADDR_IN));if(retVal == SOCKET_ERROR){printf("绑定bind失败:%d\n", WSAGetLastError());return;}if(listen(sockSrv,5/*SOMAXCONN*/) ==SOCKET_ERROR){printf("监听listen失败:%d", WSAGetLastError());return;}SOCKADDR_IN addrClient;//用于获取连接上来的人的地址信息int len = sizeof(SOCKADDR);CreateThread(NULL,NULL, (LPTHREAD_START_ROUTINE)ListenThreadProc, NULL, NULL, NULL);while(clientNum < FD_SETSIZE){//等待客户请求到来   SOCKET clientSock = accept(sockSrv, (SOCKADDR *) &addrClient, &len);if(clientSock == SOCKET_ERROR){printf("接收Accept失败:%d", WSAGetLastError());break;}else{printf("接收Accept到客户端IP:[%s]\n", inet_ntoa(addrClient.sin_addr));}FD_SET(clientSock, &g_fdClientSock);//添加到集合中去clientNum++;//每次接收到一个人就+1,目前最多接收64个客户}closesocket(sockSrv);WSACleanup();system("pause");
}

客户端:

// Tcp_client.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")void main()
{//加载套接字WSADATA wsaData;char buff[1024];memset(buff, 0, sizeof(buff));if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){printf("Failed to load Winsock");return;}SOCKADDR_IN addrSrv;addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(5099);//http默认端口addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//创建套接字SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);if(SOCKET_ERROR == sockClient){printf("Socket() error:%d", WSAGetLastError());return;}//向服务器发出连接请求if(connect(sockClient, (struct  sockaddr*)&addrSrv, sizeof(addrSrv)) == INVALID_SOCKET){printf("Connect failed:%d", WSAGetLastError());return;}int iRecvLen = 0;//发送数据char* buffSend = "hello, this is a Client....";iRecvLen = send(sockClient, buffSend, strlen(buffSend), 0);//接收数据iRecvLen = recv(sockClient, buff, sizeof(buff), 0);printf("%s\n", buff);//关闭套接字closesocket(sockClient);WSACleanup();system("pause");
}

TCP之 select模型相关推荐

  1. 基于select模型的TCP服务器

    之前的一篇博文是基于TCP的服务器和客户机程序,今天在这我要实现一个基于select模型的TCP服务器(仅实现了服务器). socket套接字编程提供了很多模型来使服务器高效的接受客户端的请求,sel ...

  2. 转:socket select模型示例

    // selectSocketMode.cpp : Defines the entry point for the console application. // #include "std ...

  3. 客户端升级为select模型

    文章目录 1 客户端升级为select模型 1.1 概述 1.2 客户端代码实现 1.3 服务端代码实现 1 客户端升级为select模型 1.1 概述 这里我们为了让客户端有时间去处理其它业务逻辑, ...

  4. 服务端升级为select模型处理多客户端

    文章目录 1 服务端升级为select模型处理多客户端 1.1 概述 1.2 服务端实现 1 服务端升级为select模型处理多客户端 1.1 概述 之前我们的设计是服务端与客户端1对1的阻塞模式网络 ...

  5. linux下多路复用模型之Select模型

    Linux关于并发网络分为Apache模型(Process per Connection (进程连接) ) 和TPC , 还有select模型,以及poll模型(一般是Epoll模型) Select模 ...

  6. 【Linux网络编程】并发服务器之select模型

    00. 目录 文章目录 00. 目录 01. 概述 02. I/O复用技术概述 03. select模型服务器实现思路 04. select模型服务器实现 05. 附录 01. 概述 服务器设计技术有 ...

  7. WinSock I/O 模型 -- Select 模型

    简介 Select 模型是 WinSock 中最常见的 I/O 模型,这篇文章我们就来看看如何使用 Select api 来实现一个简单的 TCP 服务器. API 基础 Select 模型依赖 Wi ...

  8. 网络基础 select模型

    网络基础 select 模型 (一)select简介 select模型为五种IO模型中的一种(I/O多路复用模型).该模型的函数包括select.poll.epoll等函数.这个函数能够允许指示内核等 ...

  9. 小结下select模型,poll模型和epoll模型

    关于selece,poll和epoll模型的总结 首先select,poll,epoll都是IO多路复用的机制,先是监听多个文件的描述符fd,一旦某个fd就绪后,就可以进行相应的读写操作.select ...

  10. 糖儿飞教你学C++ Socket网络编程——28. 使用select模型实现一对多通信

    在项目10中,采用多线程技术实现了TCP协议的一对多通信,但如果客户端过多,就会导致服务器端的线程数量膨胀,使得服务器的资源占用过大.能不能让TCP程序在一个线程中同时与多个客户端进行通信呢?答案是可 ...

最新文章

  1. 【1024】不整虚的,红包以备,致敬一线同僚!
  2. python【蓝桥杯vip练习题库】ADV-356字符串的操作
  3. 使用Java让android手机自动执行重复重启
  4. BI怎么选?重点看这10个技术指标
  5. 54.get set
  6. in python you can_Python编程:从入门到实践——【作业】——第十章(文件和异常)...
  7. 文件上传java前端怎么写_做一个文件上传,前端是ajax提交数据后台是java,这个错误怎么办...
  8. 剧透丨新基建沙龙第二期,你想了解的都在这里!
  9. win10系统配置服务器地址,win10系统配置服务器地址
  10. 消息持续积压几小时怎么办
  11. 【渝粤教育】21秋期末考试土木工程施工10516k1
  12. 数据结构与算法分析:第1、2章:引论和算法分析
  13. IDEA 集成Statistic插件
  14. 气象接口返回图标_中国天气网API接口
  15. 西门子plc博图与优傲UR机器人进行Profinet通讯,s7-1200/1500 与UR机器人通讯,实际应用案例使用中
  16. Zabbix以trapper方式监控MySQL备份文件
  17. UiAutomator Android 的自动测试框架(基础)
  18. ffmpeg视频特效
  19. 搭建CNN卷积神经网络(用pytorch搭建)
  20. IEEE 802.15.4和ZigBee

热门文章

  1. 问:全局变量是否可以定义在被多个.c文件包含的头文件.h中?
  2. 【presto】presto 查询hive分桶表问题
  3. 计算机招聘试题选择题,计算机考试题库:计算机基础练习题(39)
  4. 过河孙小弟scratch
  5. 网站漏洞修复公司 对网站上传文件漏洞的修复与安全加固
  6. 廊坊金彩教育:怎么做好人群标签
  7. mysqld: [ERROR] Found option without preceding group in config file D:\MySql\MyS ql\my.ini at line 1
  8. LMV324MTX单通道,双通道和四通道通用低电压轨至轨输出运算放大器TI
  9. python实现21根火柴游戏
  10. 使用vuex实现一个简单的小应用