计算机网路之服务端2.0是建立在1.0的基础上,建立了一个监听队列,实现一个服务端同时监听多个客户端,下面是2.0的模型
代码实现如下:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32")
int main()
{
// 初始化win网络版本库
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
// 1.创建协议(服务端句柄)
// AF_INET: IPV4 192.168.1.1 00::bb::::11
// SOCK_STREAM: 流式协议
// IPPROTO_TCP:TCP
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sock)
{
printf("socket create fail! %d\n", GetLastError());
return 0;
}
printf("1. socket create success\n");
// 2.绑定IP端口
struct sockaddr_in addr;
addr.sin_family = AF_INET;
// 0.0.0.0 绑定所有IP
//
addr.sin_addr.s_addr = inet_addr("0.0.0.0");
addr.sin_port = htons(7890);
if (SOCKET_ERROR == bind(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)))
{
printf("socket bind fail! %d\n", GetLastError());
return 0;
}
printf("2. socket bind success 0.0.0.0:%d\n", 7890);
// 3.监听端口
// 开门营业
listen(sock, 5);
printf("3. socket listen success\n");
SOCKET socks[1024] = { 0 };
int index = 0;
while (1)
{
FD_SET reads;
FD_ZERO(&reads);
FD_SET(sock, &reads);
for (int i = 0; i < index; ++i)
{
FD_SET(socks[i], &reads);
}
// 0超时 -1 socket错误 >0 相应的客户端数据
int nSetlect = select(NULL, &reads, NULL, NULL, NULL);
// 检测服务端句柄是否有响应
if (FD_ISSET(sock, &reads))
{
// 4.等待用户连接
struct sockaddr_in clientAddr;
int clientLen = sizeof(clientAddr);
SOCKET clientSock = accept(sock, (struct sockaddr*)&clientAddr, &clientLen);
if (INVALID_SOCKET == clientSock)
{
printf("socket accept fail! %d\n", GetLastError());
return 0;
}
printf("4. socket accept success [%s][%d]\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
socks[index++] = clientSock;
}
for (int i = 0; i < index; ++i)
{
SOCKET clientSock = socks[i];
if (FD_ISSET(clientSock, &reads))
{
// 5.接受数据
char buff[1024] = { 0 };
int recvLen = recv(clientSock, buff, 1024, 0);
printf("recv[%4d]:%s", recvLen, buff);
// TODO recvlen <=0 close
if (recvLen <= 0)
{
closesocket(clientSock);
// TODO 移除客户端句柄
socks[i] = socks[index - 1];
--index;
--i;
continue;
}
// 6.发送数据
int sendLen = send(clientSock, buff, recvLen, 0);
// sendLen == recvLen
// 7.断开客户端连接
}
}
}
// 8.关闭服务端句柄
closesocket(sock);
WSACleanup();
return 0;
}