C++ - 套接字编程 - 多线程程序抛出请求致命程序退出
C++ - Socket Programming - Multithreaded program throws Fatal program exit requested
我在 TCP 服务器上工作,它从移动应用程序接收图像数据并对其进行一些图像处理。我设法打开一个套接字并成功接收数据。但是,当尝试 运行 多个线程同时接收多个连接时会出现问题。
我采用的方法是在主线程上创建一个 ListenSocket,它接受连接并在每次请求连接时将它们传递给线程。这些是一些代码片段:
主要功能:
serverInitilization(iResult, wsaData, hints, result, ClientSocket, ListenSocket);
std::vector<FaceLandmarks> landmarks;
std::vector<std::vector<float>> features;
//main server loop
while(true)
{
cout << "Listening for connection...\n";
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
cout << "Got connection!\n";
numConn++;
thread t(recThread, ClientSocket);
cout << "Thread started. Back to listening...\n";
//t.join();
}
// shutdown the connection & cleanup
closeSocketConnection(iResult, ListenSocket);
// cleanup
return 0;
服务器初始化:
void serverInitilization(int iResult, WSADATA socketData, struct addrinfo hints
, struct addrinfo* result, SOCKET& ClientSocket, SOCKET& ListenSocket){
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &socketData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(DEFAULT_SERVER_IP, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return;
}
// Setup the TCP listening socket
iResult = ::bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return;
}
}
最后,线程函数:
void recThread(SOCKET client){
cout << "Connected in thread number: " << numConn << endl;
SOCKET current_client = client;
char recievingBuffer[DEFAULT_BUFLEN];
int recievingBufferLength = DEFAULT_BUFLEN;
int res;
while (1)
{
res = recv(current_client, recievingBuffer, recievingBufferLength, 0);
Sleep(10);
if (res == 0)
{
MessageBox(0, "error", "error", MB_OK);
closeSocketConnection(res, current_client);
break;
}
else {
printf("Bytes received: %d\n", res);
printf("Data received: ");
printf(recievingBuffer);
printf("\n");
}
}
closeSocketConnection(res, current_client);
}
现在,第一个连接处理没有问题。然而,当服务器再次尝试监听时,我得到了这个异常:
Unhandled exception at 0x00007FFF37274A30 (msvcr120.dll) in serverSideApp.exe: Fatal program exit requested.
调试的时候发现问题的原因是:
ClientSocket = accept(ListenSocket, NULL, NULL);
在这一行,在 while 循环的第二次迭代中。有人可以帮我解决这个错误并告诉我我做错了什么吗?我根据各种在线示例以及我对线程和套接字编程的理解构建了这段代码。
任何帮助将不胜感激,在此先感谢!
我使用 t.detach()
而不是 t.join()
修复了它。 join()
函数停止主线程,直到线程完成执行。但是detach()
把线程和主线程完全分开了,这样就可以运行完全独立于主线程
我会保留我的答案和问题,因为多线程 TCP 编程花了我一些时间才能很好地工作,所以也许以后有人会发现它有用。
我在 TCP 服务器上工作,它从移动应用程序接收图像数据并对其进行一些图像处理。我设法打开一个套接字并成功接收数据。但是,当尝试 运行 多个线程同时接收多个连接时会出现问题。
我采用的方法是在主线程上创建一个 ListenSocket,它接受连接并在每次请求连接时将它们传递给线程。这些是一些代码片段:
主要功能:
serverInitilization(iResult, wsaData, hints, result, ClientSocket, ListenSocket);
std::vector<FaceLandmarks> landmarks;
std::vector<std::vector<float>> features;
//main server loop
while(true)
{
cout << "Listening for connection...\n";
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
cout << "Got connection!\n";
numConn++;
thread t(recThread, ClientSocket);
cout << "Thread started. Back to listening...\n";
//t.join();
}
// shutdown the connection & cleanup
closeSocketConnection(iResult, ListenSocket);
// cleanup
return 0;
服务器初始化:
void serverInitilization(int iResult, WSADATA socketData, struct addrinfo hints
, struct addrinfo* result, SOCKET& ClientSocket, SOCKET& ListenSocket){
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &socketData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(DEFAULT_SERVER_IP, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return;
}
// Setup the TCP listening socket
iResult = ::bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return;
}
}
最后,线程函数:
void recThread(SOCKET client){
cout << "Connected in thread number: " << numConn << endl;
SOCKET current_client = client;
char recievingBuffer[DEFAULT_BUFLEN];
int recievingBufferLength = DEFAULT_BUFLEN;
int res;
while (1)
{
res = recv(current_client, recievingBuffer, recievingBufferLength, 0);
Sleep(10);
if (res == 0)
{
MessageBox(0, "error", "error", MB_OK);
closeSocketConnection(res, current_client);
break;
}
else {
printf("Bytes received: %d\n", res);
printf("Data received: ");
printf(recievingBuffer);
printf("\n");
}
}
closeSocketConnection(res, current_client);
}
现在,第一个连接处理没有问题。然而,当服务器再次尝试监听时,我得到了这个异常:
Unhandled exception at 0x00007FFF37274A30 (msvcr120.dll) in serverSideApp.exe: Fatal program exit requested.
调试的时候发现问题的原因是:
ClientSocket = accept(ListenSocket, NULL, NULL);
在这一行,在 while 循环的第二次迭代中。有人可以帮我解决这个错误并告诉我我做错了什么吗?我根据各种在线示例以及我对线程和套接字编程的理解构建了这段代码。
任何帮助将不胜感激,在此先感谢!
我使用 t.detach()
而不是 t.join()
修复了它。 join()
函数停止主线程,直到线程完成执行。但是detach()
把线程和主线程完全分开了,这样就可以运行完全独立于主线程
我会保留我的答案和问题,因为多线程 TCP 编程花了我一些时间才能很好地工作,所以也许以后有人会发现它有用。