首页 > 其他分享 >Select I/O模型来实现一个并发处理多个客户端的TCP服务器

Select I/O模型来实现一个并发处理多个客户端的TCP服务器

时间:2022-12-26 11:34:58浏览次数:42  
标签:SOCKET ret allSockSet TCP printf sListen 接字 Select 客户端

#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, “ws2_32.lib”)
int main()
{
// 加载win socket
WSADATA ws;
int ret;
ret = WSAStartup(MAKEWORD(2, 2), &ws);
if (ret != 0)
{
printf(”WSAStartup() 失败!\n”);
return -1;
}
// 创建侦听SOCKET
SOCKET sListen;
sListen = socket(AF_INET, SOCK_STREAM, 0);
if (sListen == INVALID_SOCKET)
{
printf(”socket() 失败!\n”);
return -1;
}
// 填充服务器地址结构
sockaddr_in servAddr;
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = INADDR_ANY;
servAddr.sin_port = htons(8000);

// 绑定服务器套接字
ret = bind(sListen, (sockaddr*)&servAddr, sizeof(servAddr));
if (ret == SOCKET_ERROR)
{
printf(”bind() 失败!\n”);
return -1;
}

// 开始侦听
ret = listen(sListen, 5);
if (ret == SOCKET_ERROR)
{
printf(”listen() 失败!\n”);
return -1;
}
printf(”服务器启动成功,在端口%d监听…\n”, ntohs(servAddr.sin_port));
//使用select模型
// 创建套接字集合
fd_set allSockSet; // 总的套接字集合
fd_set readSet; // 可读套接字集合
fd_set writeSet; // 可写套接字集合

FD_ZERO(&allSockSet); // 清空套接字集合
FD_SET(sListen, &allSockSet); // 将sListen套接字加入套接字集合中
char bufRecv[100]; // 接收缓冲区
// 进入服务器主循环
while(1)
{
FD_ZERO(&readSet); // 清空可读套接字
FD_ZERO(&writeSet); // 清空可写套接字
readSet = allSockSet; // 赋值
writeSet = allSockSet; // 赋值
// 调用select函数,timeout设置为NULL
ret = select(0, &readSet, 0, NULL, NULL);
//
if (ret == SOCKET_ERROR)
{
printf(”select() 失败!\n”);
return -1;
}
// 存在套接字的I/O已经准备好
if(ret > 0)
{
// 遍历所有套接字
for (int i = 0; i < allSockSet.fd_count; ++i)
{
SOCKET s = allSockSet.fd_array[i];
// 存在可读的套接字
if (FD_ISSET(s, &readSet))
{
// 可读套接字为sListen
if (s == sListen)
{
// 接收新的连接
sockaddr_in clientAddr;
int len = sizeof(clientAddr);
SOCKET sClient = accept(s, (sockaddr*)&clientAddr, &len);
// 将新创建的套接字加入到集合中
FD_SET(sClient, &allSockSet);
printf(”>>>>>有新的连接到来啦…\n”);
printf(”目前客户端数目为:%d\n”, allSockSet.fd_count - 1);
}
else // 接收客户端信息
{
ret = recv(s, bufRecv, 100, 0);
// 接收错误
if (ret == SOCKET_ERROR)
{
DWORD err = WSAGetLastError();
if (err == WSAECONNRESET)
printf(”客户端被强行关闭\n”);
else
printf(”recv() 失败!”);
// 删除套接字
FD_CLR(s, &allSockSet);
printf(”目前客户端数目为:%d\n”, allSockSet.fd_count - 1);
break;
}
if (ret == 0)
{
printf(”客户端已经退出!\n”);
// 删除套接字
FD_CLR(s, &allSockSet);
printf(”目前客户端数目为:%d\n”, allSockSet.fd_count - 1);
break;
}
bufRecv[ret] = ‘\0′;
printf(”收到的消息:%s\n”, bufRecv);
} // end else

}// end if

}// end for
} // end if
}//end while
return 0;
}

标签:SOCKET,ret,allSockSet,TCP,printf,sListen,接字,Select,客户端
From: https://www.cnblogs.com/kn-zheng/p/17005315.html

相关文章

  • select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
    select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型,原型: intselect(intmaxfd,fd_set*rdset,fd_set*wr......
  • TCP/IP概述
    7.1.1TCP/IP的分层模型7.1.2TCP/IP的分层模型特点7.1.3TCP/IP核心协议  OSI协议参考模型,它是基于国际标准化组织(ISO)的建议发展起来的,它分为7个层次:应用层、表示层......
  • python中socket使用UDP协议简单实现服务端与客户端通信
    UDP为不可靠传输,也就是发送方不关心对方是否收到消息,一般用于聊天软件。但现在的聊天软件虽然使用的是UDP协议,但已从代码层面上解决了丢失信息的问题。下面使用python代码......
  • MQTT.fx客户端的安装及开始
    MQTT.fx客户端的安装及开始下载:官网:http://mqttfx.org最新版本,但是需要安装许可证,只能免费试用三个月百度网盘:只有1.7的版本,无需许可证(推荐)Windows版(64位)ht......
  • 图文并茂解释TCPIP 3次握手4次挥手
    1.TCP与UDP的区别TCP(TransmissionControlProtocol,传输控制协议)是面向连接的,可靠的通信协议,而UDP(UserDatagramProtocol,用户数据报协议)是无连接的,不可靠的通信协议......
  • Flutter写的博客园客户端
    几个月前在博客园发帖说要用Flutter写个客户端,版本也在陆陆续续的迭代当中,软件也日臻完善起来,想着就把它开源以作Flutter学习。目前软件已经上线GoolgePlay:https://pl......
  • 初识MySQL(四)单表select查询操作
    数据准备:用户表user:createtableuser(idintunsignedprimarykeynotnullauto_increment,namevarchar(50)UNIQUEnotnull,agetinyintnotnull,......
  • 基于QT的TCP传输拆包和组包算法
    什么是TCP传输的粘包,以及为什么要拆包组包就不仔细叙述了,简而言之就是TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,数据的顺序和内容都是可靠的,但因为是机遇字......
  • tcp编程
    面试官:描述一下TCP的编程流程?答:TCP服务器端编程的一般步骤是:TCP客户端编程的一般步骤是:1.创建一个socket,用函数socket();......
  • Day11_03_Redis教程之Redis服务器客户端安装配置及配置文件详解
    Redis服务器客户端安装配置及配置文件详解一.Redis的安装在ubuntu18.04下,可以直接通过命令安装.1.更新系统环境$sudoapt-getupdate#更新软件列表$sudoapt-getupgra......