WSA error 10048 when binding server sockets
WSA 10048 is the 'Address in use' error (https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx).
I don't have windows so I can't run your code, but this error commonly occurs when a server keeps a server port reserved for a number of minutes before it can be reused.
A socket option is provided to allow faster reuse, setsockopt (SO_REUSEADDR).
In your case, you would add the following lines right after creating and checking ListenSocket
:
int optval = 1;
iResult = ::setsockopt(ListenSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
if (iResult == SOCKET_ERROR) {
std::cout << 9 << std::endl;
printf("setsockopt failed with error: %d\n", WSAGetLastError());
}
The TCP stack has good reasons for not re-issuing old port numbers immediatly after they are released, but for server ports this is unwanted behaviour. Only, the stack does not know the difference between a server and a non-server port, so we must use setsockopt.
mindoo
Updated on June 04, 2022Comments
-
mindoo almost 2 years
I started with the simple server tutorial on the msdn website in order to learn how to use sockets in client and server applications.
Once I was done following thet tutorial, I started adapting the client and server code into multithreaded proggrams in order to make a tchat client and server. Everything was going very well until I ran into WSA error 10048. I tried using different ports for each socket but it still did not solve the error.
Here is my server code :
#undef UNICODE #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> #include <stdlib.h> #include <stdio.h> #include <iostream> #include <thread> #include <vector> // Need to link with Ws2_32.lib #pragma comment (lib, "Ws2_32.lib") // #pragma comment (lib, "Mswsock.lib") //Global values //I put them as global values in order to get the server up and running. //I will try to pass them as params later on int iResult; struct addrinfo *result = NULL; struct addrinfo hints; int numClients = 0; SOCKET ClientSocket[5]; std::thread** sendReceiveThread = new std::thread*[5]; //Prototypes int listen(SOCKET ListenSocket); int accept(SOCKET ListenSocket); int sendReceive(); int shutdownFunction(SOCKET ClientSocket); #define DEFAULT_BUFLEN 512 #define DEFAULT_PORT1 "1016" #define DEFAULT_PORT2 "1017" #define DEFAULT_PORT3 "1018" #define DEFAULT_PORT4 "1019" #define DEFAULT_PORT5 "1020" int main() { std::cout << 1 << std::endl; WSADATA wsaData; SOCKET ListenSocket = INVALID_SOCKET; // Initialize Winsock std::cout << 2 << std::endl; iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { std::cout << 3 << std::endl; printf("WSAStartup failed with error: %d\n", iResult); return 1; } ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; std::thread ListenThread{ [ListenSocket](){listen(ListenSocket); } }; ListenThread.join(); return 0; } int listen(SOCKET ListenSocket) { int numPort = 1; std::vector<std::thread*> thread_vec; while (true) { if (numPort == 1) { // Resolve the server address and port std::cout << 4 << std::endl; iResult = getaddrinfo(NULL, DEFAULT_PORT1, &hints, &result); numPort++; if (iResult != 0) { std::cout << 5 << std::endl; printf("getaddrinfo failed with error: %d\n", iResult); WSACleanup(); break; } } else if (numPort == 2) { // Resolve the server address and port std::cout << 4 << std::endl; iResult = getaddrinfo(NULL, DEFAULT_PORT2, &hints, &result); numPort++; if (iResult != 0) { std::cout << 5 << std::endl; printf("getaddrinfo failed with error: %d\n", iResult); WSACleanup(); break; } } else if (numPort == 3) { // Resolve the server address and port std::cout << 4 << std::endl; iResult = getaddrinfo(NULL, DEFAULT_PORT3, &hints, &result); numPort++; if (iResult != 0) { std::cout << 5 << std::endl; printf("getaddrinfo failed with error: %d\n", iResult); WSACleanup(); break; } } else if (numPort == 4) { // Resolve the server address and port std::cout << 4 << std::endl; iResult = getaddrinfo(NULL, DEFAULT_PORT4, &hints, &result); numPort++; if (iResult != 0) { std::cout << 5 << std::endl; printf("getaddrinfo failed with error: %d\n", iResult); WSACleanup(); break; } } else if (numPort == 5) { // Resolve the server address and port std::cout << 4 << std::endl; iResult = getaddrinfo(NULL, DEFAULT_PORT5, &hints, &result); numPort++; if (iResult != 0) { std::cout << 5 << std::endl; printf("getaddrinfo failed with error: %d\n", iResult); WSACleanup(); break; } } // Create a SOCKET for connecting to server std::cout << 6 << std::endl; ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ListenSocket == INVALID_SOCKET) { std::cout << 7 << std::endl; printf("socket failed with error: %ld\n", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); break; } // Setup the TCP listening socket std::cout << 8 << std::endl; iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); if (iResult == SOCKET_ERROR) { std::cout << 9 << std::endl; printf("bind failed with error: %d\n", WSAGetLastError()); freeaddrinfo(result); closesocket(ListenSocket); WSACleanup(); break; } freeaddrinfo(result); std::cout << 10 << std::endl; iResult = listen(ListenSocket, SOMAXCONN); if (iResult == SOCKET_ERROR) { std::cout << 11 << std::endl; printf("listen failed with error: %d\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); break; } static std::thread AcceptThread{ [ListenSocket](){accept(ListenSocket); } }; thread_vec.push_back(&AcceptThread); } for (auto it : thread_vec) it->join(); return 0; } int accept(SOCKET ListenSocket) { numClients++; const int currentNumClients = numClients; for (int i = 0; i <= 5; i++) { ClientSocket[i] = INVALID_SOCKET; } // Accept a client socket std::cout << 12 << std::endl; std::cout << 13 << std::endl; ClientSocket[currentNumClients] = accept(ListenSocket, NULL, NULL); if (ClientSocket[currentNumClients] == INVALID_SOCKET) { printf("accept failed with error: %d\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } sendReceiveThread[currentNumClients] = new std::thread([](){sendReceive(); }); (*sendReceiveThread[currentNumClients]).join(); delete sendReceiveThread[currentNumClients]; return 0; } int sendReceive() { int currentNumClients = numClients; int iSendResult; char recvbuf[DEFAULT_BUFLEN]; int recvbuflen = DEFAULT_BUFLEN; // Receive until the peer shuts down the connection while(true) { std::cout << 14 << std::endl; iResult = recv(ClientSocket[currentNumClients], recvbuf, recvbuflen, 0); std::cout << iResult << std::endl; if (iResult > 0) { std::cout << 15 << std::endl; printf("Bytes received: %d\n", iResult); // Echo the buffer back to the clients std::cout << 16 << std::endl; for (int i = 1; i <= numClients; i++) { iSendResult = send(ClientSocket[currentNumClients], recvbuf, iResult, 0); if (iSendResult == SOCKET_ERROR) { std::cout << 17 << std::endl; printf("send failed with error: %d\n", WSAGetLastError()); closesocket(ClientSocket[currentNumClients]); WSACleanup(); return 1; } printf("Bytes sent: %d\n", iSendResult); } } else if (iResult == 0) { std::cout << 18 << std::endl; printf("Connection closing...\n"); break; } else { std::cout << 19 << std::endl; printf("recv failed with error: %d\n", WSAGetLastError()); std::cout << "On client #" << currentNumClients << std::endl; break; } } iResult = shutdownFunction(ClientSocket[currentNumClients]); std::cout << 22 << std::endl; // cleanup closesocket(ClientSocket[currentNumClients]); WSACleanup(); return 0; } int shutdownFunction(SOCKET ClientSocket) { std::cout << 20 << std::endl; iResult = shutdown(ClientSocket, SD_SEND); if (iResult == SOCKET_ERROR) { std::cout << 21 << std::endl; printf("shutdown failed with error: %d\n", WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } return 0; }
You might notice the different couts, those are just couts to know how the proggram behaves.
-
mindoo over 8 yearsI had done some research and I found the same link as you and the same setsockopt function but I dont understand what it really does and how I would implement it in my code.
-
EvertW over 8 yearsI have expanded the answer.
-
mindoo over 8 yearsI tried putting the piece of code you specified in your answer at the line 156 but it tells me : Error 1 error C2664: 'int setsockopt(SOCKET,int,int,const char *,int)' : cannot convert argument 4 from 'int *' to 'const char *'
-
mindoo over 8 years@dbush thanks, that was a quick and easy fix but now my code just crashes, would you have any idea of why it crashes.
-
EvertW over 8 yearsCan you find out at which line it crashes? E.g. by running the code in the debugger?
-
mindoo over 8 years@EvertW What I mean when I say it crashes is that it compiles fine but when I run it it says that the proggram has stopped working.
-
EvertW over 8 yearsI got that, that's what we have debuggers for ;-) If you are using visual studio (express), you should go through some tutorial, e.g. youtube.com/watch?v=eEJ5xKO7c3o . I found that through google by looking for "visual studio debugging tutorial".
-
mindoo over 8 yearsOh ok, I'll definitly checkout that. I never used the debugger in VS apart from when I have just plain old errors (I'm not even sure that that is the debugger)
-
mindoo over 8 years@EvertW I followed the tutorial you suggested and then I went through each line and at line 65 (where I says ListenThread.join() ) it says that my proggram has triggered a break point. If I try to hit continue, it says : Unhandled exception at 0x77B95904 (ntdll.dll) in ConsoleApplication1.exe: 0xC0000374: A heap has been corrupted (parameters: 0x77BB1378).
-
EvertW over 8 yearsThis tells you two things: 1). The bug is located in another thread. You can debug threads after putting a breakpoint at their first line. 2). The error probably has something to do with memory mis-management.
-
EvertW over 8 yearsAt the moment you do not need threads. When you create a thread and then immediatly join it, you might as well call a function directly. Is much easier to debug...
-
mindoo over 8 years@EvertW I think I'll try to just call the function directly without using a thread. And then if it doesn't work, then I'll try to go debug in the function.
-
mindoo over 8 years@EvertW So basically what I do is call the listen function directly without using a thread. I then added a if statement in order to break out of the loop when numPort is equal to 6 because that was what made my code crash. Now when I launch the server, what happens is that the server does all the setup code perfectly but when I try to connect to it with the client, on the server it says recv failed on client #1 with error 10054 and in the client, it says unable to connect to the server.
-
Jérôme Gillard about 8 yearsCorrect use would be:
int flag = 1; setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&flag, sizeof(flag));