EDIT : Server updated 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];
bool firstTime = true;
//Prototypes
int listen(SOCKET ListenSocket);
int accept(SOCKET ListenSocket);
int sendReceive();
int shutdownFunction(SOCKET ClientSocket);
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "1016"
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;
listen(ListenSocket);
return 0;
}
int listen(SOCKET ListenSocket)
{
int numPort = 1;
std::vector<std::thread*> thread_vec;
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0)
{
std::cout << 5 << std::endl;
std::cout << "getaddrinfo failed with error : " << iResult << std::endl;
WSACleanup();
return -1;
}
// 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();
return -1;
}
char 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());
return -1;
}
// 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();
return -1;
}
freeaddrinfo(result);
for (int i = 1; i < 5; i++)
{
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();
return -1;
}
std::cout << 23 << std::endl;
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;
if (firstTime == true)
{
for (int i = 0; i <= 5; i++)
{
ClientSocket[i] = INVALID_SOCKET;
}
firstTime = false;
}
// 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;
}
else{
std::cout << "Client " << currentNumClients << " connected" << std::endl;
}
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;
}
I'm currently proggramming a c++ server and client chatroom in the console using Winsock2. My problem is that the second time I launch the client, it seems to connect fine but the server doesn't seem to receive anything that it sends. One of the clients works fine and the other doesn't work.
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;
listen(ListenSocket);
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;
}
}
else if (numPort == 6)
{
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;
}
char 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());
}
// 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;
}
std::cout << 23 << std::endl;
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;
}
Here is my clients code :
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <thread>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#pragma warning(disable: 4996)
#define DEFAULT_BUFLEN 1024
#define DEFAULT_PORT "1016"
//Prototypes
int sendFunction(char *sendbuf, SOCKET ConnectionSocket);
int shutdownFunction(SOCKET ConnectSocket);
int receiveFunction(SOCKET ConnectSocket, int recvbuflen);
int inputFunction(char *sendbuf, SOCKET ConnectSocket);
int main()
{
std::cout << 1 << std::endl;
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char *sendbuf = "this is a test";
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
std::cout << 2 << std::endl;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
std::cout << 3 << std::endl;
#define IP "127.0.0.1"
iResult = getaddrinfo(IP, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
std::cout << 4 << std::endl;
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
std::cout << 5 << std::endl;
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
std::cout << 6 << std::endl;
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
std::cout << 7 << std::endl;
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
std::cout << 8 << std::endl;
break;
}
freeaddrinfo(result);
//Error management for the ConnectSocket
if (ConnectSocket == INVALID_SOCKET) {
std::cout << 9 << std::endl;
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
SOCKET ReceiveSocket = ConnectSocket;
std::thread inputThread{ [sendbuf, ConnectSocket](){inputFunction(sendbuf, ConnectSocket); } };
std::thread receiveThread{ [ReceiveSocket, recvbuflen](){receiveFunction(ReceiveSocket, recvbuflen); } };
inputThread.join();
receiveThread.join();
std::cout << 14 << std::endl;
return 0;
}
int sendFunction(char *sendbuf, SOCKET ConnectionSocket)
{
int iResult;
// Send an initial buffer
std::cout << 10 << std::endl;
if (ConnectionSocket == INVALID_SOCKET)
std::cout << 17 << std::endl;
iResult = send(ConnectionSocket, sendbuf, (int)strlen(sendbuf), 0);
std::cout << 18 << std::endl;
if (iResult == SOCKET_ERROR) {
std::cout << 11 << std::endl;
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectionSocket);
WSACleanup();
return 1;
}
std::cout << 16 << std::endl;
printf("Bytes Sent: %ld\n", iResult);
return 0;
}
int shutdownFunction(SOCKET ConnectSocket)
{
// shutdown the connection since no more data will be sent
std::cout << 12 << std::endl;
int iResult;
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
return 0;
}
int receiveFunction(SOCKET ConnectSocket, int recvbuflen)
{
char *recvContent = new char[recvbuflen];
int iResult;
std::cout << 20 << std::endl;
// Receive until the peer closes the connection
do {
std::cout << 13 << std::endl;
iResult = recv(ConnectSocket, recvContent, recvbuflen, 0);
if (iResult > 0)
{
printf("Bytes received: %d\n", iResult);
for (int i = 0; i < iResult; i++)
{
std::cout << recvContent[i];
}
std::cout << std::endl;
}
else if (iResult == 0)
{
printf("Connection closed\n");
closesocket(ConnectSocket);
WSACleanup();
}
else
{
printf("recv failed with error: %d\n", WSAGetLastError());
shutdownFunction(ConnectSocket);
closesocket(ConnectSocket);
WSACleanup();
}
} while (iResult > 0);
return 0;
}
int inputFunction(char *sendbuf, SOCKET ConnectSocket)
{
std::cout << 15 << std::endl;
std::string temp;
while (true)
{
getline(std::cin, temp);
sendbuf = new char[temp.length() + 1];
strncpy(sendbuf, temp.c_str(), temp.length());
sendbuf[temp.length()] = '\0';
std::thread sendThread{ [sendbuf, ConnectSocket](){sendFunction(sendbuf, ConnectSocket); } };
sendThread.join();
delete[] sendbuf;
}
return 0;
}
As ports, I use 1016 through 1020. I already tried changing them but it didn't change anything. As ip address, I use 127.0.0.1.
Something that I also dont really understand is why in my accept function, it doesn't print out 12 and 13 as it is supposed to do.
Any help is greatly appreciated,
mindoo
Related
I am trying to create a simple multithreaded server in C++ for Windows using Winsock. I am facing a problem that I do not know how to solve. I expect my server to be able to serve multiple clients at once. Multiple clients should be able to connect to the server and query the server and get the following response back: "This is a message from the server."
Client 1 connects and gets the response successfully. Client 2 connects and now Client 1 does not receive the reponse anymore! Only Client 2 receives a response. I expect both Client 1 and Client 2 to be able to query the server and get a response from the server at the same time.
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <chrono>
#include <thread>
#include <string>
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_IP "192.168.11.108"
#define DEFAULT_PORT "12345"
#define DEFAULT_BUFLEN 1024
void ServeClient(const SOCKET* s) {
std::thread::id threadId = std::this_thread::get_id();
std::cout << "Client with thread id " << threadId << " connected to the server." << std::endl;
char receiveBuffer[DEFAULT_BUFLEN];
int receiveBufferLength = DEFAULT_BUFLEN;
int receiveResult = SOCKET_ERROR;
char sendBuffer[] = "This is a message from the server.";
int sendBufferLength = sizeof(sendBuffer) / sizeof(sendBuffer[0]);
int sendResult = SOCKET_ERROR;
while (true) {
receiveResult = recv(*s, receiveBuffer, receiveBufferLength, 0);
if (receiveResult <= 0)
break;
sendResult = send(*s, sendBuffer, sendBufferLength, 0);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
closesocket(*s);
std::cout << "Client with thread id " << threadId << " disconnected from the server." << std::endl;
}
int main() {
int result;
WSADATA wsaData;
struct addrinfo* getAddrInfoResult = NULL;
struct addrinfo getAddrInfoHints;
result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
std::cout << "WSAStartup() failed with error code: " << result;
return 1;
}
ZeroMemory(&getAddrInfoHints, sizeof(getAddrInfoHints));
getAddrInfoHints.ai_family = AF_INET;
getAddrInfoHints.ai_socktype = SOCK_STREAM;
getAddrInfoHints.ai_protocol = IPPROTO_TCP;
getAddrInfoHints.ai_flags = AI_PASSIVE;
result = getaddrinfo(DEFAULT_IP, DEFAULT_PORT, &getAddrInfoHints, &getAddrInfoResult);
if (result != 0) {
std::cout << "getaddrinfo() failed with error code: " << result;
WSACleanup();
return 1;
}
SOCKET ServerSocket = socket(getAddrInfoResult->ai_family, getAddrInfoResult->ai_socktype, getAddrInfoResult->ai_protocol);
if (ServerSocket == INVALID_SOCKET) {
std::cout << "socket() failed with error code: " << WSAGetLastError();
freeaddrinfo(getAddrInfoResult);
WSACleanup();
return 1;
}
result = bind(ServerSocket, getAddrInfoResult->ai_addr, (int)getAddrInfoResult->ai_addrlen);
if (result == SOCKET_ERROR) {
std::cout << "bind() failed with error code: " << WSAGetLastError();
freeaddrinfo(getAddrInfoResult);
closesocket(ServerSocket);
WSACleanup();
return 1;
}
freeaddrinfo(getAddrInfoResult);
result = listen(ServerSocket, SOMAXCONN);
if (result == SOCKET_ERROR) {
std::cout << "listen() failed with error code: " << WSAGetLastError();
closesocket(ServerSocket);
WSACleanup();
return 1;
}
std::cout << "Server listening..." << std::endl;
while (true)
{
SOCKET ClientSocket = accept(ServerSocket, NULL, NULL);
if (ClientSocket != INVALID_SOCKET) {
std::thread(ServeClient, &ClientSocket).detach();
}
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
closesocket(ServerSocket);
WSACleanup();
return 0;
}
Appreciate it if someone can help. Thank you.
I recently started studying c++ and I'm following some tutorials. I was looking into sockets and I decided as a side project to create a small multithreaded server as you can see below.
I was trying to close the servers listening socket once CLIENTS_MAX_NUM reached and then reopen it once a socket disconnects, however this is giving me an error 10022 (WSAEINVAL) and I'm not quite sure what I'm doing wrong.
In case you want to reproduce the error just connect using telnet and close the client connection (ctrl+] , quit).
Any help would be greatly appreciated.
#include <iostream>
#include <vector>
#include <string>
#include <future>
#include <chrono>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
static constexpr const unsigned int PORT = 5000;
static constexpr const unsigned int CLIENTS_MAX_NUM = 1;
static constexpr const unsigned int CLIENTS_QUEUE_NUM = 10;
SOCKET server_sock;
std::vector<std::future<void>> futures;
std::mutex mtx;
void initialize_winsock() {
WSAData wsData;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &wsData);
if (wsResult != 0) {
std::cerr << WSAGetLastError() << std::endl;
WSACleanup();
exit(EXIT_FAILURE);
}
}
void bind_server_socket() {
int keep_alive = 1;
int re_use = 1;
if (setsockopt(server_sock, SOL_SOCKET, SO_KEEPALIVE, (const char*)&keep_alive, sizeof(keep_alive)) == SOCKET_ERROR) {
closesocket(server_sock);
WSACleanup();
exit(EXIT_FAILURE);
}
if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&re_use, sizeof(re_use)) == SOCKET_ERROR) {
closesocket(server_sock);
WSACleanup();
exit(EXIT_FAILURE);
}
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.S_un.S_addr = INADDR_ANY;
memset(&server.sin_zero, 0, 8);
if (bind(server_sock, (sockaddr*)&server, sizeof(sockaddr)) == SOCKET_ERROR) {
std::cerr << WSAGetLastError() << std::endl;
closesocket(server_sock);
WSACleanup();
exit(EXIT_FAILURE);
}
}
void open_server_socket(bool &listening) {
server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_sock == INVALID_SOCKET) {
std::cerr << WSAGetLastError() << std::endl;
listening = false;
WSACleanup();
exit(EXIT_FAILURE);
}
listening = true;
}
void close_server_socket(bool &listening) {
closesocket(server_sock);
listening = false;
}
void handle_client(SOCKET client_sock, sockaddr_in client) {
char buf[4096];
char host[NI_MAXHOST];
char service[NI_MAXHOST];
memset(host, 0, NI_MAXHOST);
memset(service, 0, NI_MAXHOST);
//std::cout << std::this_thread::get_id() << std::endl;
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) {
std::cout << host << " connected on port " << service << std::endl;
}
else {
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
std::cout << host << " connected on port " << ntohs(client.sin_port) << std::endl;
}
while (true) {
memset(&buf, 0, 4096);
const int bytes_received = recv(client_sock, buf, 4096, 0);
if (bytes_received == SOCKET_ERROR) {
std::cerr << WSAGetLastError() << std::endl;
WSACleanup();
}
else if (bytes_received == 0) {
std::cout << "client disconnected" << std::endl;
break;
}
else {
send(client_sock, buf, bytes_received + 1, 0);
}
}
}
int main(int argc, const char* argv[]) {
bool listening = false;
initialize_winsock();
open_server_socket(listening);
bind_server_socket();
// -----------------------------------------------------------
if (listen(server_sock, CLIENTS_QUEUE_NUM) == SOCKET_ERROR) {
std::cerr << WSAGetLastError() << std::endl;
closesocket(server_sock);
WSACleanup();
exit(EXIT_FAILURE);
}
else {
std::cout << "listening for incoming connections on port " << PORT << std::endl;
while (true) {
unsigned int removed = 0;
for (int i = 0; i < futures.size(); i++) {
auto status = futures.at(i).wait_for(std::chrono::milliseconds(0));
if (status == std::future_status::ready) {
futures.erase(futures.begin() + i);
removed++;
}
}
if (removed > 1) {
std::cout << removed << " clients removed" << std::endl;
}
else if (removed) {
std::cout << removed << " client removed" << std::endl;
}
if (futures.size() < CLIENTS_MAX_NUM && !listening) {
std::cout << "re-opening server socket" << std::endl;
open_server_socket(listening);
// BOOM <--- 10022 (WSAEINVAL) - https://learn.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2
}
if (listening) {
sockaddr_in client;
memset(&client.sin_zero, 0, 8);
int client_size = sizeof(client);
SOCKET client_sock = accept(server_sock, (sockaddr*)&client, &client_size);
if (client_sock == INVALID_SOCKET) {
std::cerr << WSAGetLastError() << std::endl;
closesocket(server_sock);
WSACleanup();
exit(EXIT_FAILURE);
}
else {
futures.emplace_back(std::async(std::launch::async, &handle_client, client_sock, client));
if (futures.size() >= CLIENTS_MAX_NUM && listening) {
std::cout << "closing server socket" << std::endl;
close_server_socket(listening);
}
std::cout << futures.size() << " clients connected" << std::endl;
}
}
}
}
// ----------------------------------------------------------
std::cout << "bye!" << std::endl;
WSACleanup();
exit(EXIT_SUCCESS);
}
After some digging I found a couple silly errors, below is the working code:
update
Also fixed the vector loop
#include <iostream>
#include <vector>
#include <string>
#include <future>
#include <chrono>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
static constexpr const unsigned int PORT = 5000;
static constexpr const unsigned int CLIENTS_MAX_NUM = 5;
static constexpr const unsigned int CLIENTS_QUEUE_NUM = 0;
void handle_client(SOCKET client_sock, sockaddr_in client) {
char buf[4096];
char host[NI_MAXHOST];
char service[NI_MAXHOST];
memset(host, 0, NI_MAXHOST);
memset(service, 0, NI_MAXHOST);
//std::cout << std::this_thread::get_id() << std::endl;
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) {
std::cout << host << " connected on port " << service << std::endl;
}
else {
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
std::cout << host << " connected on port " << ntohs(client.sin_port) << std::endl;
}
while (true) {
memset(&buf, 0, 4096);
const int bytes_received = recv(client_sock, buf, 4096, 0);
if (bytes_received == SOCKET_ERROR) {
std::cerr << WSAGetLastError() << std::endl;
WSACleanup();
}
else if (bytes_received == 0) {
std::cout << "client disconnected" << std::endl;
break;
}
else {
send(client_sock, buf, bytes_received + 1, 0);
}
}
}
void initialize_winsock() {
WSAData wsData;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &wsData);
if (wsResult != 0) {
std::cerr << WSAGetLastError() << std::endl;
WSACleanup();
exit(EXIT_FAILURE);
}
}
void bind_server_socket(SOCKET &server_sock) {
int keep_alive = 1;
int re_use = 1;
if (setsockopt(server_sock, SOL_SOCKET, SO_KEEPALIVE, (const char*)&keep_alive, sizeof(keep_alive)) == SOCKET_ERROR) {
closesocket(server_sock);
WSACleanup();
exit(EXIT_FAILURE);
}
if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&re_use, sizeof(re_use)) == SOCKET_ERROR) {
closesocket(server_sock);
WSACleanup();
exit(EXIT_FAILURE);
}
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.S_un.S_addr = INADDR_ANY;
memset(&server.sin_zero, 0, 8);
if (bind(server_sock, (sockaddr*)&server, sizeof(sockaddr)) == SOCKET_ERROR) {
std::cerr << WSAGetLastError() << std::endl;
closesocket(server_sock);
WSACleanup();
exit(EXIT_FAILURE);
}
}
void open_server_socket(SOCKET &server_sock, bool &accepting) {
server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_sock == INVALID_SOCKET) {
std::cerr << WSAGetLastError() << std::endl;
accepting = false;
WSACleanup();
exit(EXIT_FAILURE);
}
accepting = true;
}
void close_server_socket(SOCKET &server_sock, bool &accepting) {
closesocket(server_sock);
accepting = false;
}
void clear_futures(std::vector<std::future<void>> &futures) {
std::vector<std::future<void>>::iterator it = futures.begin();
while (it != futures.end()) {
auto status = (*it).wait_for(std::chrono::milliseconds(0));
if (status == std::future_status::ready) {
it = futures.erase(it);
}
else {
++it;
}
}
}
void wait_for_connections(std::vector<std::future<void>> &futures, SOCKET &server_sock, bool& accepting) {
if (listen(server_sock, CLIENTS_QUEUE_NUM) == SOCKET_ERROR) {
std::cerr << WSAGetLastError() << std::endl;
closesocket(server_sock);
WSACleanup();
exit(EXIT_FAILURE);
}
else {
std::cout << "accepting for incoming connections on port " << PORT << std::endl;
while (true) {
if (futures.size() < CLIENTS_MAX_NUM && !accepting) {
std::cout << "re-opening server socket" << std::endl;
open_server_socket(server_sock, accepting);
bind_server_socket(server_sock);
wait_for_connections(futures, server_sock, accepting);
break;
}
if (accepting) {
sockaddr_in client;
memset(&client.sin_zero, 0, 8);
int client_size = sizeof(client);
SOCKET client_sock = accept(server_sock, (sockaddr*)&client, &client_size);
if (client_sock == INVALID_SOCKET) {
std::cerr << WSAGetLastError() << std::endl;
closesocket(server_sock);
WSACleanup();
exit(EXIT_FAILURE);
}
clear_futures(futures);
futures.emplace_back(std::async(std::launch::async, &handle_client, client_sock, client));
if (futures.size() >= CLIENTS_MAX_NUM && accepting) {
std::cout << "closing server socket" << std::endl;
close_server_socket(server_sock, accepting);
}
std::cout << futures.size() << " clients connected" << std::endl;
}
}
}
}
int main(int argc, const char* argv[]) {
std::vector<std::future<void>> futures;
bool accepting = false;
SOCKET server_sock;
initialize_winsock();
open_server_socket(server_sock, accepting);
bind_server_socket(server_sock);
wait_for_connections(futures, server_sock, accepting);
std::cout << "bye!" << std::endl;
WSACleanup();
exit(EXIT_SUCCESS);
}
I'm trying to create a thread that handles client-server communication using a socket in C++.
The program throws an error
std::Invoke, No matching overloaded function found
Error C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...) noexcept(<expr>)'
I'm unable to debug the program since it crashes at startup.
Is there anything wrong in thread initialization with two parameters? Or am I missing some library, class import?
Can anyone help me out, what am I missing here?
Here's my code
#include <ws2tcpip.h>
#include <iostream>
#include <string>
#include <thread>
using namespace std;
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
PCSTR IP_ADDRESS = "192.168.1.100";
#define DEFAULT_PORT "3504"
struct client_type
{
SOCKET socket;
int id;
char received_message[DEFAULT_BUFLEN];
};
int process_client(client_type& new_client);
int main();
int process_client(client_type& new_client)
{
while (1)
{
memset(new_client.received_message, 0, DEFAULT_BUFLEN);
if (new_client.socket != 0)
{
int iResult = recv(new_client.socket, new_client.received_message, DEFAULT_BUFLEN, 0);
if (iResult != SOCKET_ERROR)
cout << new_client.received_message << endl;
else
{
//cout << "recv() failed: " << WSAGetLastError() << endl;
break;
}
}
}
if (WSAGetLastError() == WSAECONNRESET)
cout << "The server has disconnected" << endl;
return 0;
}
int main()
{
WSAData wsa_data;
struct addrinfo* result = NULL, * ptr = NULL, hints;
string sent_message = "";
client_type client = { INVALID_SOCKET, -1, "" };
int iResult = 0;
string message;
cout << "Starting Client...\n";
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (iResult != 0) {
cout << "WSAStartup() failed with error: " << iResult << endl;
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
cout << "Connecting...\n";
// Resolve the server address and port
iResult = getaddrinfo(IP_ADDRESS, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
cout << "getaddrinfo() failed with error: " << iResult << endl;
WSACleanup();
system("pause");
return 1;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
// Create a SOCKET for connecting to server
client.socket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (client.socket == INVALID_SOCKET) {
cout << "socket() failed with error: " << WSAGetLastError() << endl;
WSACleanup();
system("pause");
return 1;
}
// Connect to server.
iResult = connect(client.socket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(client.socket);
client.socket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (client.socket == INVALID_SOCKET) {
cout << "Unable to connect to server!" << endl;
WSACleanup();
system("pause");
return 1;
}
cout << "Successfully Connected" << endl;
//Obtain id from server for this client;
recv(client.socket, client.received_message, DEFAULT_BUFLEN, 0);
message = client.received_message;
if (message != "Server is full")
{
client.id = atoi(client.received_message);
thread my_thread(process_client, client);
while (1)
{
getline(cin, sent_message);
iResult = send(client.socket, sent_message.c_str(), strlen(sent_message.c_str()), 0);
if (iResult <= 0)
{
cout << "send() failed: " << WSAGetLastError() << endl;
break;
}
}
//Shutdown the connection since no more data will be sent
my_thread.detach();
}
else
cout << client.received_message << endl;
cout << "Shutting down socket..." << endl;
iResult = shutdown(client.socket, SD_SEND);
if (iResult == SOCKET_ERROR) {
cout << "shutdown() failed with error: " << WSAGetLastError() << endl;
closesocket(client.socket);
WSACleanup();
system("pause");
return 1;
}
closesocket(client.socket);
WSACleanup();
system("pause");
return 0;
}```
I boiled your program down to a minimal, reproducible example:
#include <thread>
struct client_type
{
};
int process_client(client_type& new_client)
{
return 0;
}
int main()
{
client_type client;
std::thread my_thread(process_client, client);
}
This small snippet fails to compile, and trying to compile gives the error you mention.
Why does this fail? Lets look at the std::thread constructor. In the notes section we find this:
The arguments to the thread function are moved or copied by value. If
a reference argument needs to be passed to the thread function, it has
to be wrapped (e.g., with std::ref or std::cref).
And indeed std::thread my_thread(process_client, std::ref(client)); compiles without issue.
I've been trying for days to send a short, plain-text email to myself with C++. I'm using Visual Studio Express 2015. I'm eventually hoping to email automatic alerts to myself. I am using a Gmail account. I can't seem to manage to get this to work. I can send data, but can't receive. The server is closing my connection with Error 10054. (You can read about what that error means on this page.)
Here is the history: I have cobbled all this together from lots of S.O. posts and MSDN articles. I used to have a functional WSASetSocketSecurity section in this code, but for whatever reason, my connection attempts were timing out, so I omitted it. At this point, I will settle for the server not severing my connection when I send EHLO or HELO.
I'm really at a loss for how to proceed. Days of exploration, dozens of read articles, hundreds of dead ends. I hope that you'll forgive the few bits of junk code and that S.O. removed my hand alignments. Please take a look, let me know what I am doing wrong, let me know of any improper style, or anything else that offends your good-coder sensibilities. Many thanks.
#include "stdafx.h"
#include <exception>
#include <string>
#include <iostream> // In-out stream objects for development
#include <stdio.h> // Standard in-out for development
#include <winsock2.h> // For making socket connection to email server
#include <Mstcpip.h>
#include <Ws2tcpip.h> // Enhanced protocols to assist winsock2.h
#pragma comment(lib, "Ws2_32.lib") // Library for winsock2.h
#pragma comment(lib, "Fwpuclnt.lib") // Library for winsock2.h
#define BUFFER_SIZE 512
using namespace std;
void cleanup(SOCKET ConnectSocket, struct addrinfo *result) {
if (ConnectSocket != INVALID_SOCKET) {
closesocket(ConnectSocket);
}
freeaddrinfo(result);
WSACleanup();
cout << "socket closed" << endl;
cin.get(); // Development only
}
int _tmain(int argc, char* argv[]) {
// Initialize email parameters
char bccAddresses[64] = "";
char fromAddress[64] = "my_email#host.com";
char msg[512] = "Hello world!";
char port[12] = "465";
char serverName[64] = "smtp.host.com";
char toAddresses[64] = "my_email#host.com";
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo *ptr = NULL;
struct addrinfo hints;
WSADATA wsaData;
try {
// Initialize Winsock
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult == SOCKET_ERROR) {
cout << "Error " << iResult << endl;
throw std::exception("WSAStartup failed\n");
}
cout << "WSAStartup successful: " << iResult << endl;
// Set up the hints socket address structure
ZeroMemory(&hints, sizeof(hints));
hints.ai_flags = AI_SECURE;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(serverName, port, &hints, &result);
if (iResult == SOCKET_ERROR) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("getaddrinfo failed\n");
}
cout << "getaddrinfo successful: " << iResult << endl;
// Connect to the socket
ptr = result;
ConnectSocket = WSASocket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol, NULL, 0, 0);
if (ConnectSocket == INVALID_SOCKET) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("Error at socket\n");
}
cout << "WSASocket successful: " << iResult << endl;
// Connect via the socket
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
cout << "Error " << WSAGetLastError() << endl;
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
throw std::exception("Unable to connect to server!\n");
}
cout << "connect successful: " << iResult << endl;
// Send message
char sendBuffer[BUFFER_SIZE] = "What is your malfunction";
char recvBuffer[BUFFER_SIZE];
sprintf_s(sendBuffer, BUFFER_SIZE, "EHLO %s%s", serverName, "\r\n");
iResult = send(ConnectSocket, sendBuffer, BUFFER_SIZE, 0);
if (iResult == SOCKET_ERROR) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("WINSOCK send failed\n");
}
cout << "Sent:\n" << sendBuffer << "Byte count: " << iResult << endl;
iResult = recv(ConnectSocket, recvBuffer, BUFFER_SIZE, 0);
if (iResult == SOCKET_ERROR) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("WINSOCK recv failed\n");
}
cout << "EHLO response: " << iResult << endl;
sprintf_s(sendBuffer, BUFFER_SIZE, "QUIT%s", "\r\n");
iResult = send(ConnectSocket, sendBuffer, BUFFER_SIZE, 0);
if (iResult == SOCKET_ERROR) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("WINSOCK send failed\n");
}
cout << "Sent:\n" << sendBuffer << "Byte count: " << iResult << endl;
iResult = recv(ConnectSocket, recvBuffer, BUFFER_SIZE, 0);
if (iResult < 0) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("WINSOCK recv failed\n");
}
cout << "Quit response: " << iResult << endl;
// Shutdown the connection
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("shutdown failed\n");
}
// Clean up
cleanup(ConnectSocket, result);
return 0;
}
catch (std::exception err) {
printf(err.what());
cleanup(ConnectSocket, result);
return 1;
}
catch (...) {
printf("Unknown error\n");
cleanup(ConnectSocket, result);
return 2;
}
}
Three parts to this answer.
MIME Encode the username and password.
ACTUALLY send the username and password! :)
Some servers are skeptical and want you to say HELO or EHLO twice.
I will post full code soon. Although I feel I was about 40% of the way there, I owe my success to this site: http://www.coastrd.com/smtps.
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.
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.