如果在线程中执行,简单的 Winsock 服务器将无法工作
Simple Winsock server doesn't work if executed in thread
我想在一个程序中有多个服务器,但如果我尝试将服务器放在一个函数中并使用线程执行它,它就会崩溃(没有编译错误)。抱歉,代码很长,但需要它来证明我的问题:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include <Windows.h>
#include <thread>
#pragma comment(lib, "Ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
int server()
{
WSADATA data;
WSAStartup(MAKEWORD(2, 2), &data);
sockaddr_in listen_address;
listen_address.sin_family = AF_INET;
listen_address.sin_port = htons(1000);
listen_address.sin_addr.S_un.S_addr = INADDR_ANY;
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);
bind(listen_socket, (sockaddr*)&listen_address, sizeof(listen_address));
listen(listen_socket, SOMAXCONN);
sockaddr client_info = { 0 };
int socklen;
SOCKADDR_IN addr;
int addrlen = sizeof(addr);
listen_socket = accept(listen_socket, (struct sockaddr*)&client_info, &addrlen);
if (listen_socket != INVALID_SOCKET)
{
std::cout << "New connection" << std::endl;
}
int iResult, iSendResult;
char buffer[1024]{ 0 };
do {
iResult = recv(listen_socket, buffer, sizeof(buffer), 0);
if (iResult > 0) {
std::cout << buffer << std::endl;
}
else if (iResult == 0)
std::cout << "Closing connection" << std::endl;
else {
printf("recv failed: %d\n", WSAGetLastError());
closesocket(listen_socket);
WSACleanup();
return 1;
}
} while (iResult > 0);
//clean up
system("pause");
closesocket(listen_socket);
WSACleanup();
return 0;
}
int main() {
std::thread server_thread(server);
return 0;
}
如果你只是 运行 server() 函数它工作正常但在一个线程中它崩溃了。
崩溃是因为当 main()
退出时你的 std::thread
超出范围,但你没有在线程上调用 join()
或 detach()
,所以std::thread
析构函数正在调用 std::terminate()
终止您的进程。
试试这个:
#include <iostream>
#include <thread>
#include <cstdlib>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <Windows.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
void server()
{
int iResult;
char buffer[1024];
sockaddr_in listen_address;
listen_address.sin_family = AF_INET;
listen_address.sin_port = htons(1000);
listen_address.sin_addr.S_un.S_addr = INADDR_ANY;
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket == INVALID_SOCKET) {
iResult = WSAGetLastError();
std::cerr << "socket failed: " << iResult << "\n";
return;
}
if (bind(listen_socket, (sockaddr*)&listen_address, sizeof(listen_address)) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "bind failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
if (listen(listen_socket, 1) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "listen failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
sockaddr client_info = { 0 };
int socklen;
int addrlen = sizeof(client_info);
SOCKET client_socket = accept(listen_socket, (struct sockaddr*)&client_info, &addrlen);
if (client_socket == INVALID_SOCKET) {
iResult = WSAGetLastError();
std::cerr << "accept failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
closesocket(listen_socket);
std::cout << "New connection" << std::endl;
do {
iResult = recv(client_socket, buffer, sizeof(buffer), 0);
if (iResult <= 0) {
if (iResult == 0) {
std::cout << "Closing connection" << std::endl;
}
else {
iResult = WSAGetLastError();
std::cerr << "recv failed: " << iResult << "\n";
}
break;
}
std::cout.write(buffer, iResult);
std::cout << std::endl;
}
while (true);
//clean up
closesocket(client_socket);
}
int main() {
WSADATA data;
int iResult = WSAStartup(MAKEWORD(2, 2), &data);
if (iResult != 0) {
std::cerr << "WSAStartup failed: " << iResult << "\n";
return 0;
}
std::thread server_thread(server);
std::system("pause");
server_thread.join();
WSACleanup();
return 0;
}
现在,每个服务器有 1 个客户端并不是特别有用。要使用 1 个服务器处理多个客户端,您可以在循环中调用 accept()
,然后为每个接受的客户端创建一个单独的线程(您可以使用更好的方法,但下面仅用于演示目的),例如:
#include <iostream>
#include <thread>
#include <vector>
#include <atomic>
#include <cstdlib>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <Windows.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
std::atomic<bool> stopRunning = false;
void client(SOCKET client_socket)
{
int iResult;
char buffer[1024];
fd_set rfds;
timeval timeout;
std::cout << "New connection" << std::endl;
while (!stopRunning.load()) {
iResult = recv(client_socket, buffer, sizeof(buffer), 0);
if (iResult == SOCKET_ERROR) {
iResult = WSAGetLastError();
if (iResult != WSAEWOULDBLOCK) {
std::cerr << "recv failed: " << iResult << "\n";
break;
}
FD_ZERO(&rfds);
FD_SET(client_socket, &rfds);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
iResult = select(0, &rfds, NULL, NULL, &timeout);
if (iResult < 0) {
iResult = WSAGetLastError();
std::cerr << "select failed: " << iResult << "\n";
break;
}
if (iResult == 0)
continue;
}
else if (iResult == 0) {
std::cout << "Closing connection" << std::endl;
break;
}
else {
std::cout.write(buffer, iResult);
std::cout << std::endl;
}
}
//clean up
closesocket(client_socket);
}
void server()
{
int iResult;
sockaddr_in listen_address;
listen_address.sin_family = AF_INET;
listen_address.sin_port = htons(1000);
listen_address.sin_addr.S_un.S_addr = INADDR_ANY;
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket == INVALID_SOCKET) {
iResult = WSAGetLastError();
std::cerr << "socket failed: " << iResult << "\n";
return;
}
u_long mode = 1;
if (ioctlsocket(listen_socket, FIONBIO, &mode) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "ioctlsocket failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
if (bind(listen_socket, (sockaddr*)&listen_address, sizeof(listen_address)) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "bind failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
if (listen(listen_socket, SOMAXCONN) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "listen failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
std::vector<std::thread> clients;
sockaddr client_info;
int addrlen;
SOCKET client_socket;
fd_set rfds;
timeval timeout;
while (!stopRunning.load()) {
FD_ZERO(&rfds);
FD_SET(listen_socket, &rfds);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
iResult = select(0, &rfds, NULL, NULL, &timeout);
if (iResult < 0) {
iResult = WSAGetLastError();
std::cerr << "select failed: " << iResult << "\n";
break;
}
if (iResult > 0) {
addrlen = sizeof(client_info);
client_socket = accept(listen_socket, (struct sockaddr*)&client_info, &addrlen);
if (client_socket == INVALID_SOCKET) {
iResult = WSAGetLastError();
std::cerr << "accept failed: " << iResult << "\n";
break;
}
if (ioctlsocket(client_socket, FIONBIO, &mode) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "ioctlsocket failed: " << iResult << "\n";
closesocket(client_socket);
continue;
}
threads.push_back(std::thread(client, client_socket));
}
}
closesocket(listen_socket);
stopRunning = true;
for (auto &t : threads) {
t.join();
}
}
int main() {
WSADATA data;
int iResult = WSAStartup(MAKEWORD(2, 2), &data);
if (iResult != 0) {
std::cerr << "WSAStartup failed: " << iResult << "\n";
return 0;
}
std::thread server_thread(server);
std::system("pause");
stopRunning = true;
server_thread.join();
WSACleanup();
return 0;
}
或者,如果所有套接字都处于非阻塞模式,您根本不需要 运行 每个客户端都在自己的线程中,例如:
#include <iostream>
#include <thread>
#include <vector>
#include <atomic>
#include <cstdlib>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <Windows.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
std::atomic<bool> stopRunning = false;
void server()
{
int iResult;
sockaddr_in listen_address;
listen_address.sin_family = AF_INET;
listen_address.sin_port = htons(1000);
listen_address.sin_addr.S_un.S_addr = INADDR_ANY;
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket == INVALID_SOCKET) {
iResult = WSAGetLastError();
std::cerr << "socket failed: " << iResult << "\n";
return;
}
u_long mode = 1;
if (ioctlsocket(listen_socket, FIONBIO, &mode) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "ioctlsocket failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
if (bind(listen_socket, (sockaddr*)&listen_address, sizeof(listen_address)) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "bind failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
if (listen(listen_socket, SOMAXCONN) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "listen failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
std::vector<SOCKET> clients;
SOCKET client_socket;
sockaddr client_info;
int addrlen;
fd_set rfds;
timeval timeout;
char buffer[1024];
while (!stopRunning.load()) {
FD_ZERO(&rfds);
FD_SET(listen_socket, &rfds);
for(auto sckt : clients) {
FD_SET(sckt, &rfds);
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
iResult = select(0, &rfds, NULL, NULL, &timeout);
if (iResult < 0) {
iResult = WSAGetLastError();
std::cerr << "select failed: " << iResult << "\n";
break;
}
if (iResult == 0)
continue;
if (FD_ISSET(listen_socket, &rfds)) {
addrlen = sizeof(client_info);
client_socket = accept(listen_socket, (struct sockaddr*)&client_info, &addrlen);
if (client_socket == INVALID_SOCKET) {
iResult = WSAGetLastError();
std::cerr << "accept failed: " << iResult << "\n";
break;
}
if (ioctlsocket(client_socket, FIONBIO, &mode) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "ioctlsocket failed: " << iResult << "\n";
closesocket(client_socket);
}
else {
std::cout << "New connection" << std::endl;
clients.push_back(client_socket);
}
}
for (size_t i = 0; i < clients.size();) {
client_socket = clients[i];
if (FD_ISSET(client_socket, &rfds)) {
iResult = recv(client_socket, buffer, sizeof(buffer), 0);
if (iResult == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "recv failed: " << iResult << "\n";
closesocket(client_socket);
clients.erase(clients.begin()+i);
continue;
}
if (iResult == 0) {
std::cout << "Closing connection" << std::endl;
closesocket(client_socket);
clients.erase(clients.begin()+i);
continue;
}
std::cout.write(buffer, iResult);
std::cout << std::endl;
}
++i;
}
}
//clean up
closesocket(listen_socket);
for (auto sckt : clients) {
closesocket(sckt);
}
}
int main() {
WSADATA data;
int iResult = WSAStartup(MAKEWORD(2, 2), &data);
if (iResult != 0) {
std::cerr << "WSAStartup failed: " << iResult << "\n";
return 0;
}
std::thread server_thread(server);
std::system("pause");
stopRunning = true;
server_thread.join();
WSACleanup();
return 0;
}
我想在一个程序中有多个服务器,但如果我尝试将服务器放在一个函数中并使用线程执行它,它就会崩溃(没有编译错误)。抱歉,代码很长,但需要它来证明我的问题:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include <Windows.h>
#include <thread>
#pragma comment(lib, "Ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
int server()
{
WSADATA data;
WSAStartup(MAKEWORD(2, 2), &data);
sockaddr_in listen_address;
listen_address.sin_family = AF_INET;
listen_address.sin_port = htons(1000);
listen_address.sin_addr.S_un.S_addr = INADDR_ANY;
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);
bind(listen_socket, (sockaddr*)&listen_address, sizeof(listen_address));
listen(listen_socket, SOMAXCONN);
sockaddr client_info = { 0 };
int socklen;
SOCKADDR_IN addr;
int addrlen = sizeof(addr);
listen_socket = accept(listen_socket, (struct sockaddr*)&client_info, &addrlen);
if (listen_socket != INVALID_SOCKET)
{
std::cout << "New connection" << std::endl;
}
int iResult, iSendResult;
char buffer[1024]{ 0 };
do {
iResult = recv(listen_socket, buffer, sizeof(buffer), 0);
if (iResult > 0) {
std::cout << buffer << std::endl;
}
else if (iResult == 0)
std::cout << "Closing connection" << std::endl;
else {
printf("recv failed: %d\n", WSAGetLastError());
closesocket(listen_socket);
WSACleanup();
return 1;
}
} while (iResult > 0);
//clean up
system("pause");
closesocket(listen_socket);
WSACleanup();
return 0;
}
int main() {
std::thread server_thread(server);
return 0;
}
如果你只是 运行 server() 函数它工作正常但在一个线程中它崩溃了。
崩溃是因为当 main()
退出时你的 std::thread
超出范围,但你没有在线程上调用 join()
或 detach()
,所以std::thread
析构函数正在调用 std::terminate()
终止您的进程。
试试这个:
#include <iostream>
#include <thread>
#include <cstdlib>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <Windows.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
void server()
{
int iResult;
char buffer[1024];
sockaddr_in listen_address;
listen_address.sin_family = AF_INET;
listen_address.sin_port = htons(1000);
listen_address.sin_addr.S_un.S_addr = INADDR_ANY;
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket == INVALID_SOCKET) {
iResult = WSAGetLastError();
std::cerr << "socket failed: " << iResult << "\n";
return;
}
if (bind(listen_socket, (sockaddr*)&listen_address, sizeof(listen_address)) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "bind failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
if (listen(listen_socket, 1) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "listen failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
sockaddr client_info = { 0 };
int socklen;
int addrlen = sizeof(client_info);
SOCKET client_socket = accept(listen_socket, (struct sockaddr*)&client_info, &addrlen);
if (client_socket == INVALID_SOCKET) {
iResult = WSAGetLastError();
std::cerr << "accept failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
closesocket(listen_socket);
std::cout << "New connection" << std::endl;
do {
iResult = recv(client_socket, buffer, sizeof(buffer), 0);
if (iResult <= 0) {
if (iResult == 0) {
std::cout << "Closing connection" << std::endl;
}
else {
iResult = WSAGetLastError();
std::cerr << "recv failed: " << iResult << "\n";
}
break;
}
std::cout.write(buffer, iResult);
std::cout << std::endl;
}
while (true);
//clean up
closesocket(client_socket);
}
int main() {
WSADATA data;
int iResult = WSAStartup(MAKEWORD(2, 2), &data);
if (iResult != 0) {
std::cerr << "WSAStartup failed: " << iResult << "\n";
return 0;
}
std::thread server_thread(server);
std::system("pause");
server_thread.join();
WSACleanup();
return 0;
}
现在,每个服务器有 1 个客户端并不是特别有用。要使用 1 个服务器处理多个客户端,您可以在循环中调用 accept()
,然后为每个接受的客户端创建一个单独的线程(您可以使用更好的方法,但下面仅用于演示目的),例如:
#include <iostream>
#include <thread>
#include <vector>
#include <atomic>
#include <cstdlib>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <Windows.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
std::atomic<bool> stopRunning = false;
void client(SOCKET client_socket)
{
int iResult;
char buffer[1024];
fd_set rfds;
timeval timeout;
std::cout << "New connection" << std::endl;
while (!stopRunning.load()) {
iResult = recv(client_socket, buffer, sizeof(buffer), 0);
if (iResult == SOCKET_ERROR) {
iResult = WSAGetLastError();
if (iResult != WSAEWOULDBLOCK) {
std::cerr << "recv failed: " << iResult << "\n";
break;
}
FD_ZERO(&rfds);
FD_SET(client_socket, &rfds);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
iResult = select(0, &rfds, NULL, NULL, &timeout);
if (iResult < 0) {
iResult = WSAGetLastError();
std::cerr << "select failed: " << iResult << "\n";
break;
}
if (iResult == 0)
continue;
}
else if (iResult == 0) {
std::cout << "Closing connection" << std::endl;
break;
}
else {
std::cout.write(buffer, iResult);
std::cout << std::endl;
}
}
//clean up
closesocket(client_socket);
}
void server()
{
int iResult;
sockaddr_in listen_address;
listen_address.sin_family = AF_INET;
listen_address.sin_port = htons(1000);
listen_address.sin_addr.S_un.S_addr = INADDR_ANY;
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket == INVALID_SOCKET) {
iResult = WSAGetLastError();
std::cerr << "socket failed: " << iResult << "\n";
return;
}
u_long mode = 1;
if (ioctlsocket(listen_socket, FIONBIO, &mode) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "ioctlsocket failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
if (bind(listen_socket, (sockaddr*)&listen_address, sizeof(listen_address)) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "bind failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
if (listen(listen_socket, SOMAXCONN) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "listen failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
std::vector<std::thread> clients;
sockaddr client_info;
int addrlen;
SOCKET client_socket;
fd_set rfds;
timeval timeout;
while (!stopRunning.load()) {
FD_ZERO(&rfds);
FD_SET(listen_socket, &rfds);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
iResult = select(0, &rfds, NULL, NULL, &timeout);
if (iResult < 0) {
iResult = WSAGetLastError();
std::cerr << "select failed: " << iResult << "\n";
break;
}
if (iResult > 0) {
addrlen = sizeof(client_info);
client_socket = accept(listen_socket, (struct sockaddr*)&client_info, &addrlen);
if (client_socket == INVALID_SOCKET) {
iResult = WSAGetLastError();
std::cerr << "accept failed: " << iResult << "\n";
break;
}
if (ioctlsocket(client_socket, FIONBIO, &mode) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "ioctlsocket failed: " << iResult << "\n";
closesocket(client_socket);
continue;
}
threads.push_back(std::thread(client, client_socket));
}
}
closesocket(listen_socket);
stopRunning = true;
for (auto &t : threads) {
t.join();
}
}
int main() {
WSADATA data;
int iResult = WSAStartup(MAKEWORD(2, 2), &data);
if (iResult != 0) {
std::cerr << "WSAStartup failed: " << iResult << "\n";
return 0;
}
std::thread server_thread(server);
std::system("pause");
stopRunning = true;
server_thread.join();
WSACleanup();
return 0;
}
或者,如果所有套接字都处于非阻塞模式,您根本不需要 运行 每个客户端都在自己的线程中,例如:
#include <iostream>
#include <thread>
#include <vector>
#include <atomic>
#include <cstdlib>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <Windows.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
std::atomic<bool> stopRunning = false;
void server()
{
int iResult;
sockaddr_in listen_address;
listen_address.sin_family = AF_INET;
listen_address.sin_port = htons(1000);
listen_address.sin_addr.S_un.S_addr = INADDR_ANY;
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket == INVALID_SOCKET) {
iResult = WSAGetLastError();
std::cerr << "socket failed: " << iResult << "\n";
return;
}
u_long mode = 1;
if (ioctlsocket(listen_socket, FIONBIO, &mode) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "ioctlsocket failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
if (bind(listen_socket, (sockaddr*)&listen_address, sizeof(listen_address)) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "bind failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
if (listen(listen_socket, SOMAXCONN) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "listen failed: " << iResult << "\n";
closesocket(listen_socket);
return;
}
std::vector<SOCKET> clients;
SOCKET client_socket;
sockaddr client_info;
int addrlen;
fd_set rfds;
timeval timeout;
char buffer[1024];
while (!stopRunning.load()) {
FD_ZERO(&rfds);
FD_SET(listen_socket, &rfds);
for(auto sckt : clients) {
FD_SET(sckt, &rfds);
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
iResult = select(0, &rfds, NULL, NULL, &timeout);
if (iResult < 0) {
iResult = WSAGetLastError();
std::cerr << "select failed: " << iResult << "\n";
break;
}
if (iResult == 0)
continue;
if (FD_ISSET(listen_socket, &rfds)) {
addrlen = sizeof(client_info);
client_socket = accept(listen_socket, (struct sockaddr*)&client_info, &addrlen);
if (client_socket == INVALID_SOCKET) {
iResult = WSAGetLastError();
std::cerr << "accept failed: " << iResult << "\n";
break;
}
if (ioctlsocket(client_socket, FIONBIO, &mode) == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "ioctlsocket failed: " << iResult << "\n";
closesocket(client_socket);
}
else {
std::cout << "New connection" << std::endl;
clients.push_back(client_socket);
}
}
for (size_t i = 0; i < clients.size();) {
client_socket = clients[i];
if (FD_ISSET(client_socket, &rfds)) {
iResult = recv(client_socket, buffer, sizeof(buffer), 0);
if (iResult == SOCKET_ERROR) {
iResult = WSAGetLastError();
std::cerr << "recv failed: " << iResult << "\n";
closesocket(client_socket);
clients.erase(clients.begin()+i);
continue;
}
if (iResult == 0) {
std::cout << "Closing connection" << std::endl;
closesocket(client_socket);
clients.erase(clients.begin()+i);
continue;
}
std::cout.write(buffer, iResult);
std::cout << std::endl;
}
++i;
}
}
//clean up
closesocket(listen_socket);
for (auto sckt : clients) {
closesocket(sckt);
}
}
int main() {
WSADATA data;
int iResult = WSAStartup(MAKEWORD(2, 2), &data);
if (iResult != 0) {
std::cerr << "WSAStartup failed: " << iResult << "\n";
return 0;
}
std::thread server_thread(server);
std::system("pause");
stopRunning = true;
server_thread.join();
WSACleanup();
return 0;
}