服务端骨架:
#include <iostream>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include <windows.h>
int main()
{
WSADATA lpWSAData;
WSAStartup(MAKEWORD(2, 2), &lpWSAData);
SOCKADDR_IN saddr{ 0 };
saddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
saddr.sin_family = AF_INET;
saddr.sin_port = htons(9527);
SOCKET SerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(SerSocket, (PSOCKADDR)&saddr, sizeof(saddr));
SOCKET arrSocket[WSA_MAXIMUM_WAIT_EVENTS]{ 0 };
WSAEVENT arrEvent[WSA_MAXIMUM_WAIT_EVENTS]{ 0 };
WSAEVENT nEvent = WSACreateEvent();
WSAEventSelect(SerSocket, nEvent, FD_ACCEPT);
DWORD dwindex = 0;
arrSocket[dwindex] = SerSocket;
arrEvent[dwindex] = nEvent;
dwindex++;
listen(SerSocket, SOMAXCONN);
while (true)
{
DWORD EventIndex = WSAWaitForMultipleEvents(dwindex, arrEvent, FALSE, WSA_INFINITE, FALSE);
EventIndex -= WSA_WAIT_EVENT_0;
WSANETWORKEVENTS NetworkEvents;
WSAEnumNetworkEvents(arrSocket[EventIndex], arrEvent[EventIndex], &NetworkEvents);
if (NetworkEvents.lNetworkEvents & FD_ACCEPT)
{
if (NetworkEvents.iErrorCode[FD_ACCEPT_BIT] == 0)
{
SOCKADDR_IN caddr{ 0 };
int length = sizeof(caddr);
SOCKET NewSocket = accept(SerSocket, (PSOCKADDR)&caddr, &length);
nEvent = WSACreateEvent();
WSAEventSelect(NewSocket, nEvent, FD_READ|FD_WRITE|FD_CLOSE);
arrSocket[dwindex] = NewSocket;
arrEvent[dwindex] = nEvent;
dwindex++;
printf("Client IP:%s Prot:%d\r\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
}
}
else if (NetworkEvents.lNetworkEvents & FD_READ)
{
if (NetworkEvents.iErrorCode[FD_READ_BIT] == 0)
{
char szbuffer[1024]{ 0 };
recv(arrSocket[EventIndex], szbuffer, sizeof(szbuffer), 0);
printf("Client Data:%s\r\n", szbuffer);
std::string str = "收到";
send(arrSocket[EventIndex], str.c_str(), str.length(), 0);
}
}
else if (NetworkEvents.lNetworkEvents & FD_WRITE)
{
if (NetworkEvents.iErrorCode[FD_WRITE_BIT] == 0)
{
printf("The client is ready\r\n");
}
}
else if (NetworkEvents.lNetworkEvents & FD_CLOSE)
{
for (size_t i = 0; i < dwindex; i++)
{
WSACloseEvent(arrEvent[EventIndex]);
closesocket(arrSocket[EventIndex]);
dwindex--;
}
}
}
WSACleanup();
system("pause");
return 0;
}
客户端骨架:
#include <iostream>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include <windows.h>
#include <process.h>
void RecvData(PVOID pt)
{
SOCKET sock = *(SOCKET*)pt;
char szbuffer[1024]{ 0 };
while (true)
{
if (recv(sock, szbuffer, sizeof(szbuffer), 0) == SOCKET_ERROR)
{
DWORD dwError = WSAGetLastError();
if (dwError == WSAETIMEDOUT || dwError == WSAENETDOWN || dwError == WSAECONNRESET)
{
closesocket(sock);
WSACleanup();
return;
}
if (dwError == WSAEWOULDBLOCK)
{
Sleep(5);
continue;
}
}
std::cout << "Server Data:" << szbuffer << std::endl;
}
}
int main()
{
WSADATA lpWSAData;
WSAStartup(MAKEWORD(2, 2), &lpWSAData);
SOCKADDR_IN caddr{ 0 };
caddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
caddr.sin_family = AF_INET;
caddr.sin_port = htons(9527);
SOCKET CliSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int iMode = 1;//这行代码将套接字设置为非阻塞模式。这意味着在调用 connect、send 或 recv 等函数时,如果操作不能立即完成,函数不会阻塞,而是立即返回一个错误。
ioctlsocket(CliSocket, FIONBIO, (u_long*)&iMode);
connect(CliSocket, (PSOCKADDR)&caddr, sizeof(caddr));
_beginthread(RecvData, 0, &CliSocket);
while (true)
{
std::cout << "Input:";
std::string str;
std::cin >> str;
send(CliSocket, str.c_str(), str.length(), 0);
Sleep(20);
}
system("pause");
return 0;
}