网络通信——select模型
借用下一个博主的图:
link
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/fbfde96bf6694e27f04e3f858893d61e.png)
说明都在注释中,代码里主要的函数解释可以看我转载的其他博客。
服务器代码
#include "stdafx.h"
#include <WinSock2.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define PORT 9527
SOCKET StartSever()
{
WSADATA data = { 0 };
if (WSAStartup(MAKEWORD(2, 2), &data))
{
printf("WSAStartup failed\n");
return 0;
}
SOCKET sockSever = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockSever == INVALID_SOCKET)
{
printf("Create socket error");
return 0;
}
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.S_un.S_addr = INADDR_ANY;
service.sin_port = htons(PORT);
if (bind(sockSever, (sockaddr*)&service, sizeof(service)) == SOCKET_ERROR)
{
printf("bind failed\n");
return 0;
}
if (listen(sockSever, SOMAXCONN) == SOCKET_ERROR)
{
printf("listen error\n");
return 0;
}
return sockSever;
}
int _tmain(int argc, _TCHAR* argv[])
{
SOCKET sockSever =StartSever();
SOCKET ArrSocket[WSA_MAXIMUM_WAIT_EVENTS] = { 0 };
WSAEVENT ArrEvent[WSA_MAXIMUM_WAIT_EVENTS] = { 0 };
DWORD nEventTotal = 0;
WSAEVENT AcceptEvent = WSACreateEvent();
WSAEventSelect(sockSever, AcceptEvent, FD_ACCEPT | FD_CLOSE);
ArrSocket[nEventTotal] = sockSever;
ArrEvent[nEventTotal] = AcceptEvent;
++nEventTotal;
while (TRUE)
{
DWORD index = WSAWaitForMultipleEvents(nEventTotal, ArrEvent, FALSE, WSA_INFINITE, FALSE);
WSANETWORKEVENTS NetWorkEvent = { 0 };
WSAEnumNetworkEvents(ArrSocket[index - WSA_WAIT_EVENT_0], ArrEvent[index - WSA_WAIT_EVENT_0], &NetWorkEvent);
if (NetWorkEvent.lNetworkEvents & FD_ACCEPT)
{
if (NetWorkEvent.iErrorCode[FD_ACCEPT_BIT] != 0)
{
break;
}
SOCKET sockClient = accept(ArrSocket[index - WSA_WAIT_EVENT_0], NULL, NULL);
if (sockClient == INVALID_SOCKET)
{
cout << "连接失败" << endl;
break;
}
WSAEVENT clientEvent = WSACreateEvent();
WSAEventSelect(sockClient, clientEvent, FD_READ | FD_WRITE | FD_CLOSE);
ArrSocket[nEventTotal] = sockClient;
ArrEvent[nEventTotal] = clientEvent;
++nEventTotal;
}
if (NetWorkEvent.lNetworkEvents & FD_READ)
{
if (NetWorkEvent.iErrorCode[FD_READ_BIT] != 0)
{
cout << "接收失败";
break;
}
char buf[2048] = { 0 };
recv(ArrSocket[index - WSA_WAIT_EVENT_0], buf, sizeof(buf), 0);
struct sockaddr_in sa;
int len = sizeof(sa);
getpeername(ArrSocket[index - WSA_WAIT_EVENT_0], (struct sockaddr *)&sa, &len);
cout << inet_ntoa(sa.sin_addr)<<":"<<buf << endl;
}
if (NetWorkEvent.lNetworkEvents & FD_WRITE)
{
if (NetWorkEvent.iErrorCode[FD_WRITE_BIT] != 0)
{
break;
}
}
if (NetWorkEvent.lNetworkEvents & FD_CLOSE)
{
if (NetWorkEvent.iErrorCode[FD_CLOSE_BIT] != 0)
{
continue;
}
closesocket(ArrSocket[index - WSA_WAIT_EVENT_0]);
}
}
if (sockSever != INVALID_SOCKET)
{
closesocket(sockSever);
}
WSACleanup();
return 0;
}
客户端代码
#include "stdafx.h"
#include "windows.h"
#include "iostream"
#include "process.h"
#include <string>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
void Receive(void *param)
{
string msg;
while (1)
{
SOCKET clientSocket = *(SOCKET*)(param);
char recvbuf[2048] = {};
if (recv(clientSocket, recvbuf, 2048, 0) == SOCKET_ERROR)
{
cout << "数据接受失败" << endl;
}
else
{
msg = recvbuf;
char sendPlayerName[5] = { 0 };
int len = strlen(recvbuf);
copy(&recvbuf[1], &recvbuf[5], sendPlayerName);
msg = msg.substr(5, len - 5);
cout << sendPlayerName << "对你说:" << msg<<endl;
}
}
}
void Send(void *param)
{
while (1)
{
SOCKET clientSocket = *(SOCKET*)(param);
char sendbuf[2048] = {};
cin.getline(sendbuf, 2048);
if (send(clientSocket, sendbuf, strlen(sendbuf), 0) == SOCKET_ERROR)
{
cout << "发送消息失败!";
}
else
cout << "发送消息成功" << endl;
}
}
int main()
{
cout << "-----------个人客户端-----------" << endl;
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
cout << "套接字初始化失败!"<<endl;
}
SOCKET clientSocket;
if ((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
{
cout << "套接字创建失败!"<<endl;
}
Sleep(30);
struct sockaddr_in ClientAddress;
memset(&ClientAddress, 0, sizeof(sockaddr_in));
ClientAddress.sin_family = AF_INET;
ClientAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
if (bind(clientSocket, (sockaddr*)&ClientAddress, sizeof(ClientAddress)) == SOCKET_ERROR)
{
cout << "套接字绑定失败!" << endl;
return 0;
}
struct sockaddr_in SeverAddress;
memset(&SeverAddress, 0, sizeof(sockaddr_in));
SeverAddress.sin_family = AF_INET;
SeverAddress.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
SeverAddress.sin_port = htons(9527);
if (connect(clientSocket, (sockaddr*)&SeverAddress, sizeof(SeverAddress)) == SOCKET_ERROR)
{
cout << "客户端:和服务器连接失败!"<<endl;
return 0;
}
else
cout << "与服务器连接成功!" << endl;
_beginthread(Receive, 0, &clientSocket);
_beginthread(Send, 0, &clientSocket);
Sleep(INFINITE);
if (clientSocket != INVALID_SOCKET) {
closesocket(clientSocket);
clientSocket = INVALID_SOCKET;
}
WSACleanup();
cout << "客户端退出!" << endl;
return 0;
}
运行效果
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/2f0b5dd4a6d49d75222b5bcab78a2519.png)