Клиентский код резко прерывается при подключении к серверу на C++ через winsock API
Недавно я делал многопоточное серверное приложение, которое способно подключаться к нескольким клиентам. Но когда я запустил клиентское приложение, произошло некоторое исключение библиотеки времени выполнения с диалоговым окном "Debug Assertion Failed". Я не в состоянии выяснить точную причину этой ошибки. Я использую winsock API в Visual Studio Ultimate 2013. Может ли кто-нибудь помочь мне найти решение? Любая помощь будет очень признательна!
Что я уже пробовал:
Клиент:
#include <windows.h> #include <winsock.h> #include <stdio.h> #include <iostream> #include <signal.h> #include <stdio.h> using namespace std; #pragma comment (lib, "Ws2_32.lib") #pragma comment (lib, "Mswsock.lib") #pragma comment (lib, "AdvApi32.lib") //DECLARATIONS //error trapping signals #define SIGINT 2 #define SIGKILL 9 #define SIGQUIT 3 // SOCKETS SOCKET sock, client; void s_handle(int s) { if (sock) closesocket(sock); if (client) closesocket(client); WSACleanup(); Sleep(10); cout << "EXIT SIGNAL :" << s; exit(0); } void s_cl(char *a, int x) { cout << a; s_handle(x + 1000); } int main() { HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN | FOREGROUND_INTENSITY); //SetConsoleTitle(".:: Basic Echo Client By KOrUPt 07 ::. "); //Declarations DWORD poll; int res, i = 1, port = 999; char buf[100]; char msg[100] = ""; char ip[15]; WSADATA data; signal(SIGINT, s_handle); signal(SIGKILL, s_handle); signal(SIGQUIT, s_handle); cout << "\t\tEcho This is a Client"; cout << "\n\n\n\t\tEnter IP to connect to: "; gets(ip); sockaddr_in ser; sockaddr addr; ser.sin_family = AF_INET; ser.sin_port = htons(123); //Set the port ser.sin_addr.s_addr = inet_addr(ip); //Set the address we want to connect to memcpy(&addr, &ser, sizeof(SOCKADDR_IN)); res = WSAStartup(MAKEWORD(1, 1), &data); //Start Winsock cout << "\n\nWSAStartup" << "\nVersion: " << data.wVersion << "\nDescription: " << data.szDescription << "\nStatus: " << data.szSystemStatus << endl; if (res != 0) s_cl("WSAStarup failed", WSAGetLastError()); sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create the socket if (sock == INVALID_SOCKET) s_cl("Invalid Socket ", WSAGetLastError()); else if (sock == SOCKET_ERROR) s_cl("Socket Error)", WSAGetLastError()); else cout << "Socket Established" << endl; res = connect(sock, &addr, sizeof(addr)); //Connect to the server if (res != 0) { s_cl("SERVER UNAVAILABLE", res); } else { cout << "\nConnected to Server: "; memcpy(&ser, &addr, sizeof(SOCKADDR)); } char RecvdData[100] = ""; int ret; while (true) { strcpy(buf, ""); cout << "\nEnter message to send ->\n"; fgets(buf, sizeof(buf), stdin); Sleep(5); res = send(sock, buf, sizeof(buf), 0); if (res == 0) { //0==other side terminated conn printf("\nSERVER terminated connection\n"); Sleep(40); closesocket(client); client = 0; break; } else if (res == SOCKET_ERROR) { //-1 == send error printf("Socket error\n"); Sleep(40); s_handle(res); break; } ret = recv(sock, RecvdData, sizeof(RecvdData), 0); if (ret > 0) { cout << endl << RecvdData; strcpy(RecvdData, ""); } } closesocket(client); WSACleanup(); }
Сервер:
#include <windows.h> #include <stdlib.h> #include <stdio.h> #include <winsock.h> #include <iostream> using namespace std; #pragma comment (lib, "Ws2_32.lib") #pragma comment (lib, "Mswsock.lib") #pragma comment (lib, "AdvApi32.lib") // our thread for recving commands DWORD WINAPI receive_cmds(LPVOID lpParam) { cout << "thread created\r\n"; // set our socket to the socket passed in as a parameter SOCKET current_client = (SOCKET)lpParam; // buffer to hold our recived data char buf[100]; // buffer to hold our sent data char sendData[100]; // for error checking int res; // our recv loop while (true) { res = recv(current_client, buf, sizeof(buf), 0); // recv cmds Sleep(2); if (res == 0) { //MessageBox(0, "error", "error", MB_OK); closesocket(current_client); ExitThread(0); } if (strstr(buf, "hello")) { // greet this user cout << "\nrecived hello cmd"; strcpy(sendData, "hello, greetings from server\n"); Sleep(2); send(current_client, sendData, sizeof(sendData), 0); } else if (strstr(buf, "bye")) { // dissconnected this user cout << "\nrecived bye cmd\n"; strcpy(sendData, "cya\n"); Sleep(2); send(current_client, sendData, sizeof(sendData), 0); // close the socket associted with this client and end this thread closesocket(current_client); ExitThread(0); } else { strcpy(sendData, "Invalid cmd\n"); Sleep(2); send(current_client, sendData, sizeof(sendData), 0); } // clear buffers strcpy(sendData, ""); strcpy(buf, ""); } } int main() { printf("Starting up multi-threaded TCP server"); // our masterSocket(socket that listens for connections) SOCKET sock; // for our thread DWORD thread; WSADATA wsaData; sockaddr_in server; // start winsock int ret = WSAStartup(0x101, &wsaData); // use highest version of winsock avalible if (ret != 0) { return 0; } // fill in winsock struct ... server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(123); // listen on telnet port 23 // create our socket sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { return 0; } // bind our socket to a port(port 123) if (bind(sock, (sockaddr*)&server, sizeof(server)) != 0) { return 0; } // listen for a connection if (listen(sock, 5) != 0) { return 0; } // socket that we sendrecv data on SOCKET client; sockaddr_in from; int fromlen = sizeof(from); // loop forever while (true) { // accept connections client = accept(sock, (struct sockaddr*)&from, &fromlen); cout << "Client connected\r\n"; // create our recv_cmds thread and parse client socket as a parameter CreateThread(NULL, 0, receive_cmds, (LPVOID)client, 0, &thread); } // shutdown winsock closesocket(sock); WSACleanup(); // exit return 0; }
Patrice T
Диалоговое окно "ошибка утверждения отладки"
Дайте полное сообщение об ошибке !
apurv625
Ошибка возникла из-за объявления сигнала #define SIGKILL 9,
#определите SIGQUIT 3. Когда я удалил эти объявления, он начал работать нормально. Является ли это хорошим подходом для удаления этих деклараций?
Richard MacCutchan
Нет, это не очень хорошая идея. Сначала вам нужно отладить приложение и выяснить причину утверждения.
Jochen Arndt
Затем пусть приложение остановится и будет отлажено, чтобы узнать, где оно терпит неудачу.
Диалоговое окно утверждения содержит информацию об исходном файле и номере строки, в которой произошло утверждение. Вы можете открыть исходный файл, чтобы проверить, в какой функции произошла ошибка и какой переменный / параметр является недопустимым. Затем проверьте в своем коде, где эта функция вызывается.