//select 特点 (轮询)
//可监控的文件描述符取决于sizeof(fdset)值
//将文件描述符加入select监控集的同时,使用数组保存select监控的文件描述符
//select返回时将数组中的文件描述符,与监控的文件描述进行比较
//select 缺点
//每次调用都要设置文件描述符集合,接口使用角度不方便
//每次调用都要把fd集合从用户态拷贝到内核态开销比较大
//每次调用都要在内核态遍历fd集合监听那些数据发生变化
//select支持的文件描述符数量太小
server
#include"pch.h"
#include<Winsock2.h>
#include<iostream>
#include<stdio.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
int connect_size = 0;
SOCKET g_clientsock[FD_SETSIZE];
DWORD WINAPI WorkThread(LPVOID lpParamter);
int main(int argc, char* argv[])
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
DWORD dwThreadId;
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8888);
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
bind(sock, (SOCKADDR*)&addr, sizeof(SOCKADDR));
listen(sock, 3);
HANDLE handle = CreateThread(NULL, 0, WorkThread, NULL, 0, &dwThreadId);
CloseHandle(handle);
SOCKADDR_IN client;
int len = sizeof(SOCKADDR_IN);
printf("server init ok\n");
while (1)
{
SOCKET sclient = accept(sock, (SOCKADDR*)&client, &len);
printf("client:%s :%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
g_clientsock[connect_size++] = sclient;
}
return 0;
}
//定义fd集合()
//套接字句柄加入fd集合
//调用select检测套接字读写性,返回数据到达的socket
//对fd集合进程检查
//相应I/O处理返回步骤1
DWORD WINAPI WorkThread(LPVOID lpParamter)
{
FD_SET fdRead;
int ret = 0; //记录字节数
TIMEVAL tw; //设置超时等待
tw.tv_sec = 1;
tw.tv_usec = 0;
char buf[256] = "";
while (1)
{
FD_ZERO(&fdRead);
for (int i = 0;i < connect_size;i++)
{
FD_SET(g_clientsock[i], &fdRead);
}
ret = select(0, &fdRead, NULL, NULL, &tw);
if (ret == 0) //没有链接或读事件
{
continue;
}
for (int i = 0;i < connect_size;i++)
{
if (FD_ISSET(g_clientsock[i], &fdRead)) //相同则处理
{
ret = recv(g_clientsock[i], buf, 256, 0);
if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
//客户端socket关闭
printf("client %d closed\n", g_clientsock[i]);
closesocket(g_clientsock[i]);
if (i < connect_size)
{
g_clientsock[i--] = g_clientsock[--connect_size];
}
}
else //正常则回显数据
{
printf("接收到socket %d的数据:%s\n", g_clientsock[i], buf);
}
}
}
}
return 0;
}
clien
// client.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include"pch.h"
#include<Winsock2.h>
#include<stdio.h>
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
int main(int argc, char* argv[])
{
//请求版本号
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
//创建
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//连接
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8888);
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int r = connect(sock, (sockaddr*)&addr, sizeof(addr));
//收发数据
char buf[256];
printf("请输入数据");
while (1)
{
memset(buf, NULL, 256);
scanf("%s", buf);
int ret = send(sock, buf, strlen(buf), NULL);
if (ret > 0)
{
printf("发送成功");
}
}
closesocket(sock);
WSACleanup();
system("pause");
return 0;
}