Winsock single client server send and receive simultaneously - c++

I have a problem with simple Winsock chat application in C++. I've written a code that enables the user to choose if he wants to send data or receive the data and depending on users choice, the appropriate functions are executed. What I would like to achieve, is that the user can BOTH send and receive data. How could I approach it? Please note that I don't want to use multiple client, I just want to send and receive data by server and send and receive data by client simultaneously.
Edit: I added my code.
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <ctime>
int main()
{
string IP;
int userType;
// Ask the user if he is server or client
cout << "Hi, which type of user are you? 1 - Server, 2 - Client" <<endl;
cin >> userType;
// depending on the declared user type, execute the appropriate code
if (userType == 1)
{
//initialize winsock and create a socket
WSAData wsaData; // initialize
iResult = WSAStartup(MAKEWORD(2,1), &wsaData);
if (iResult != NO_ERROR) // check for errors
cout << "Error at WSAStartup()" <<endl;
else
cout << "WSAStartup() is OK." <<endl;
// create socket
sockSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // create a socket
if (sockSocket == INVALID_SOCKET) // check for errors
{
cout << "Error at socket(): " << WSAGetLastError();
WSACleanup();
return true;
}
else
cout << "Socket() is OK." <<endl;
return true;
// bind to socket
service.sin_addr.s_addr = inet_addr("0.0.0.0");
service.sin_family = AF_INET;
service.sin_port = htons(55555);
if (bind(sockSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) // cheking for errors
{
cout << "Bind() failed." << endl;
closesocket(sockSocket);
return true;
}
else
cout << "Bind() is OK." <<endl;
// listen
listen(sockSocket, SOMAXCONN);
if (listen(sockSocket, 10) == SOCKET_ERROR) // check for errors
{
cout << "Error listening on socket." << endl;
return true;
}
else
cout << "Listen() is OK." <<endl;
//accept connection
servlen = sizeof(service);
cout << "Waiting for user to connect..." << endl;
acceptSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(acceptSocket = accept(sockSocket, (SOCKADDR*)&service, &servlen))
{
cout << "A coonnection was found" <<endl<<endl;
}
sockSocket = acceptSocket;
// receive messages
do
{
std::string message;
char Buffer[512];
iResult = recv(sockSocket, Buffer, 512, 0);
Buffer[iResult] = '\0';
message = Buffer;
currentDate();
std::cout << Buffer <<endl<<endl;
}while(iResult>0);
closesocket(sockSocket);
WSACleanup();
}
else if (userType == 2)
{
// exactly the same code as for server part to initialize and create socket
// ask for the ip the user wants to connect to
cout << "Hi what's the IP that you want to connect to?" <<endl;
cin >> IP;
// connect to socket
conService.sin_addr.s_addr = inet_addr(IP); // connect to the ipnuted IP
conService.sin_family = AF_INET;
conService.sin_port = htons(55555); // should the port also be the argument?
if (connect(sockSocket, (SOCKADDR*)&conService, sizeof(conService)) == SOCKET_ERROR) // check for errors
{
cout << "Failed to connect: " << WSAGetLastError();
WSACleanup();
return true;
}
else
{
cout << "Connected." <<endl;
}
// send messages
for (;;)
{
std::string message;
std::getline(std::cin, message);
unsigned int Length = strlen(message.c_str());
if(Length>512)
Length = 512;
currentDate();
iResult = send(sockSocket, message.c_str(),Length,0);
}
closesocket(sockSocket);
WSACleanup();
}
WSACleanup();
return 0;
}
Edit2: As Lemy suggested in the comment, I need to have a second thread (as the first one is simply what's going on in the main function). From what I understood, I can use CreateThread function. My problem of how to both send and receive messages is solved (I should create another thread), but now I have problem with implementing the solution. As I wrote in the comment below Lemy's answer, I get such error referring to the line where I use CreateThread function (HANDLE hThread = CreateThread(0,0,&ReadingThread,acceptSocket,0,&dwThreadID);):
invalid conversion from 'SOCKET {aka unsigned int}' to 'PVOID {aka void*}' [-fpermissive]| and
invalid conversion from 'DWORD {aka long unsigned int}' to 'PDWORD {aka long unsigned int*}' [-fpermissive]
Any hints for that? Hope this makes my question more specific(if not pls tell me what should I specify more).

You need to have the client and server continuously reading in the background for the lifetime of the connection, and then they can send data in parallel whenever needed. Move your reading logic into a separate thread, eg:
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <ctime>
DWORD WINAPI ReadingThread(LPVOID param)
{
SOCKET s = (SOCKET) param;
char Buffer[512];
int iResult;
do
{
iResult = recv(s, Buffer, 512, 0);
if (iResult <= 0) break;
Buffer[iResult] = '\0';
std::cout << "Recv: " << message << std::endl;
}
while (true);
return 0;
}
int main()
{
int userType;
HANDLE hThread;
DWORD dwThreadID;
//initialize winsock and create a socket
WSAData wsaData; // initialize
iResult = WSAStartup(MAKEWORD(2,1), &wsaData);
if (iResult != NO_ERROR) // check for errors
{
std::cout << "Error at WSAStartup()" << std::endl;
return 0;
}
std::cout << "WSAStartup() is OK." << std::endl;
// Ask the user if he is server or client
std::cout << "Hi, which type of user are you? 1 - Server, 2 - Client" << std::endl;
std::cin >> userType;
// depending on the declared user type, execute the appropriate code
if (userType == 1)
{
// create socket
sockSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // create a socket
if (sockSocket == INVALID_SOCKET) // check for errors
{
std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
WSACleanup();
return 0;
}
std::cout << "Socket() is OK." << std::endl;
// bind to socket
service.sin_addr.s_addr = INADDR_ANY;
service.sin_family = AF_INET;
service.sin_port = htons(55555);
if (bind(sockSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) // cheking for errors
{
std::cout << "Error at bind(): " << WSAGetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}
std::cout << "Bind() is OK." << std::endl;
// listen
if (listen(sockSocket, 10) == SOCKET_ERROR) // check for errors
{
std::cout << "Error at listen(): " << WSAGetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}
std::cout << "Listen() is OK." << std::endl;
//accept connection
servlen = sizeof(service);
std::cout << "Waiting for user to connect..." << std::endl;
acceptSocket = accept(sockSocket, (SOCKADDR*)&service, &servlen);
if (acceptSocket != INVALID_SOCKET)
{
std::cout << "Error at accept(): " << WSAGetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}
std::cout << "A client has connected" << std::endl << std::endl;
// receive messages
hThread = CreateThread(NULL, 0, &ReadingThread, (void*)acceptSocket, 0, &dwThreadID);
if (!hThread)
{
std::cout << "Error at CreateThread(): " << GetLastError() << std::endl;
closesocket(acceptSocket);
closesocket(sockSocket);
WSACleanup();
return 0;
}
// send messages
do
{
std::string message;
if (!std::getline(std::cin, message))
break;
if (send(acceptSocket, msg.c_str(), msg.length(), 0) == SOCKET_ERROR)
{
std::cout << "Error at send(): " << WSAGetLastError() << std::endl;
break;
}
}
while (true);
closesocket(acceptSocket);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
closesocket(sockSocket);
WSACleanup();
}
else if (userType == 2)
{
// create socket
sockSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // create a socket
if (sockSocket == INVALID_SOCKET) // check for errors
{
std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
WSACleanup();
return 0;
}
std::cout << "Socket() is OK." << std::endl;
// ask for the ip the user wants to connect to
std::string IP;
std::cout << "Hi what's the IP that you want to connect to?" << std::endl;
std::cin >> IP;
// connect to socket
conService.sin_addr.s_addr = inet_addr(IP.c_str()); // connect to the ipnuted IP
conService.sin_family = AF_INET;
conService.sin_port = htons(55555); // should the port also be the argument?
if (connect(sockSocket, (SOCKADDR*)&conService, sizeof(conService)) == SOCKET_ERROR) // check for errors
{
std::cout << "Failed to connect: " << WSAGetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}
std::cout << "Connected." << std::endl;
// receive messages
hThread = CreateThread(NULL, 0, &ReadingThread, (void*)sockSocket, 0, &dwThreadID);
if (!hThread)
{
std::cout << "Error at CreateThread(): " << GetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}
// send messages
do
{
std::string message;
if (!std::getline(std::cin, message))
break;
if (send(sockSocket, msg.c_str(), msg.length(), 0) == SOCKET_ERROR)
{
std::cout << "Error at send(): " << WSAGetLastError() << std::endl;
break;
}
}
while (true);
closesocket(sockSocket);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
WSACleanup();
}
else
{
std::cout << "Invalid type entered!" << std::endl;
WSACleanup();
return 0;
}
return 0;
}

Related

Can't send Message from Server( C++ Socket)

I'm new to C++ Socket and my Server can't send message to its client. The send() function return -1 always and it seems to have a problem with accpSocket. However Client can do that smoothly and I don't know what's wrong. Please help me thank you so much!
Server
#include<WinSock2.h>
#include<WS2tcpip.h>
#include<iostream>
#include<sdkddkver.h>
#include<winsock.h>
using namespace std;
int main() {
SOCKET serverSocket, acceptSocket = INVALID_SOCKET;
int port = 2403;
WSADATA wsaData;
int wsaerr;
//Step 1: Set up dll
WORD versionRequested = MAKEWORD(2, 2);
wsaerr = WSAStartup(versionRequested, &wsaData);
if (wsaerr)
cout << "The winsock dll not found";
else {
cout << "The winsock dll found\n";
cout << "Winsock dll status: " << wsaData.szSystemStatus << endl;
}
//Step 2: Set up server socket
serverSocket = INVALID_SOCKET;
serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET) {
cout << "Error at socket: " << WSAGetLastError();
WSACleanup();
return 0;
}
else
cout << "Server socket successfull!\n";
//Step 3: Binding socket
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.S_un.S_addr = INADDR_ANY;
service.sin_port = htons(port);
if (bind(serverSocket, (sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) {
cout << "Binding failed! " << WSAGetLastError();
return 0;
}
else
cout << "Binding complete!\n";
// Step 4: Listen to the connections
if (listen(serverSocket, 1) == SOCKET_ERROR) {
cout << "Listen failed! " << WSAGetLastError();
return 0;
}
else
cout << "Waiting for connections ...";
SOCKET accpSocket = accept(serverSocket, NULL, NULL);
if (accpSocket == INVALID_SOCKET) {
cout << "Accepting failed! " << WSAGetLastError();
WSACleanup();
return -1;
}
else
cout << "Accept connection!\n";
char recvMess[2000];
char sendMess[2000];
int byterecv = recv(accpSocket, recvMess, sizeof(recvMess), 0);
cout << "Client: " << recvMess << endl;
cout << "Server: ";
cin.getline(sendMess, 2000);
int bytesend = send(acceptSocket, sendMess, 2000, 0);
if (bytesend <= 0)
cout << "Unsent";
return 0;
}
Client
#include<iostream>
#include<WinSock2.h>
#include<WS2tcpip.h>
using namespace std;
int main() {
int port = 2403;
WSADATA wsaData;
int wsaerr;
SOCKET clientSocket;
WORD versionRequested = MAKEWORD(2, 2);
wsaerr = WSAStartup(versionRequested, &wsaData);
if (wsaerr)
cout << "Winsock dll not found!";
else {
cout << "Winsock dll is ok!\n";
cout << "Status: " << wsaData.szSystemStatus << endl;
}
clientSocket = INVALID_SOCKET;
clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSocket == INVALID_SOCKET) {
cout << "Set up client socket failed" << WSAGetLastError();
WSACleanup();
return 0;
}
else
cout << "Set up complete!\n";
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_port = htons(port);
if (inet_pton(clientService.sin_family, "127.0.0.1", &clientService.sin_addr) <= 0) {
cout << "Invalid address!";
return -1;
}
if ((connect(clientSocket, (SOCKADDR*)&clientService, sizeof(clientService))) == SOCKET_ERROR) {
cout << "Connection failed!\n";
WSACleanup();
return 0;
}
else
cout << "Connection complete!\n";
char sendMess[2000];
char recvMess[2000];
cout << "Client: ";
cin.getline(sendMess, 2000);
int bytesend = send(clientSocket, sendMess, 2000, 0);
int byterecv = recv(clientSocket, recvMess, 2000, 0);
if (byterecv <= 0)
cout << "Nothing";
else
cout << "Server" << recvMess << endl;
return 0;
}
int bytesend = send(acceptSocket, sendMess, 2000, 0);
is not sending to a connected socket. acceptSocket was defined at the top of main and then ignored up until the call to send
As a general rule of thumb, keep variable definition close to first use.
In the server at
SOCKET serverSocket, acceptSocket = INVALID_SOCKET;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Killlllll meeeeee!!!!
remove acceptSocket to prevent future mistakes and in
int bytesend = send(acceptSocket, sendMess, 2000, 0);
replace acceptSocket with the socket that was actually accepted, accpSocket.
Side notes:
Never ignore the return codes.
int byterecv = recv(accpSocket, recvMess, sizeof(recvMess), 0);
could fail and return -1 or return 0 if the socket was disconnected, yet the program will still
cout << "Client: " << recvMess << endl;
And worse, there's no guarantee that recvMess will be null-terminated, recv on a streaming socket gives you what the socket has available or becomes available up to the maximum number of bytes requested, so if there is any data read, make sure byterecv is a valid index in recvMess by only reading sizeof(recvMess) - 1 bytes and then forcing termination with recvMess[byterecv] = '\0'; before printing.
send(acceptSocket, sendMess, 2000, 0); sends all 2000 bytes of sendMess regardless of how many bytes were read with cin.getline(sendMess, 2000);. Use
send(acceptSocket, sendMess, cin.gcount(), 0);
instead. Add on an extra byte (cin.gcount() + 1) if you want to send the null terminator.

(C++ multithread / socket) When two clients connect with server, first connection disconnected

I'm making simple chatting program with c++.
The structure of the server program like this,
■ MAIN
check client connection
if client connected -> make sub thread to connection with client
■ SUB THREAD
recv message from client
when client disconnected, delete User(custom class) Object from userList(std::vector)
The problem is, when I execute one client, sending message to server works well.
And execute second client(it means two clients have connection with server at the same time), second client send message is fine, but when send message to server with first client, first client disconnected from server.
I tried:
When I add dump User Object to userList(0), it works well. (why?) => I think something wrong with initialize vector, but i'm not sure.
I did't use mutex yet, but I think this problem is not cause by not using mutex.
this is my codes:
Server.cpp
#include "Server.h"
void communicateClient(std::vector<User*>* userList, User* user) {
bool clientConnected = true;
char recvMessage[Constants::NETWORK_MESSAGE_SIZE] = { 0, };
while (clientConnected) {
if (recv(user->getUserSocket(), recvMessage, sizeof(recvMessage), 0) == -1) {
std::cout
<< Constants::LOG_NETWORK
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b1) << "."
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b2) << "."
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b3) << "."
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b4) << ":"
<< std::to_string(user->getUserSockAddrIn().sin_port) << " client disconnected" << std::endl;
clientConnected = false;
}
else {
std::cout
<< Constants::LOG_NETWORK
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b1) << "."
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b2) << "."
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b3) << "."
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b4) << ":"
<< std::to_string(user->getUserSockAddrIn().sin_port) << " send message: "
<< recvMessage << std::endl;
}
}
closesocket(user->getUserSocket());
std::vector<User*>::iterator userIterator;
for (userIterator = userList->begin(); userIterator != userList->end(); userIterator++) {
if ((*userIterator)->getUserId() == user->getUserId()) {
delete(*userIterator);
userList->erase(userIterator);
break;
}
}
std::cout << "client count: " << userList->size() << std::endl;
}
int main() {
WSADATA wsaData;
SOCKET serverSocket;
SOCKADDR_IN serverAddr;
std::cout << Constants::LOG_START << "Chatting server started" << std::endl;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cout << Constants::LOG_ERROR << "Error WSAStartup()" << std::endl;
return -1;
}
serverSocket = socket(AF_INET, SOCK_STREAM, Constants::PROTOCOL);
if (serverSocket == INVALID_SOCKET) {
std::cout << Constants::LOG_ERROR << "Error socket()" << std::endl;
}
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
inet_pton(AF_INET, Constants::SERVER_IP.c_str(), &serverAddr.sin_addr);
serverAddr.sin_port = htons(Constants::SERVER_PORT);
if (bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cout << Constants::LOG_ERROR << "Error bind()" << std::endl;
}
if (listen(serverSocket, Constants::CLIENT_CONNECT_LIMIT) == SOCKET_ERROR) {
std::cout << Constants::LOG_ERROR << "Error listen()" << std::endl;
}
std::vector<User*> userList;
std::vector<std::thread*> clientConnectionThread;
serverState = true;
while (serverState) {
std::cout << Constants::LOG_WAIT << "waiting client connection..." << std::endl;
SOCKADDR_IN clientSockAddrIn;
SOCKET clientSocket;
int clientSockAddrInSize = sizeof(clientSockAddrIn);
clientSocket = accept(serverSocket, (SOCKADDR*)&clientSockAddrIn, &clientSockAddrInSize);
if (clientSocket == SOCKET_ERROR) {
std::cout << Constants::LOG_ERROR << "Error accept()" << std::endl;
}
else {
std::cout
<< Constants::LOG_SUCCESS
<< std::to_string(clientSockAddrIn.sin_addr.S_un.S_un_b.s_b1) << "."
<< std::to_string(clientSockAddrIn.sin_addr.S_un.S_un_b.s_b2) << "."
<< std::to_string(clientSockAddrIn.sin_addr.S_un.S_un_b.s_b3) << "."
<< std::to_string(clientSockAddrIn.sin_addr.S_un.S_un_b.s_b4) << ":"
<< std::to_string(clientSockAddrIn.sin_port) << " client connected" << std::endl;
User* user = new User;
user->setUserSocket(clientSocket);
user->setUserSockAddrIn(clientSockAddrIn);
userList.push_back(user);
clientConnectionThread.push_back(new std::thread(communicateClient, &userList, std::ref(userList.back())));
std::cout << "client count: " << userList.size() << std::endl;
}
}
std::vector<std::thread>::iterator threadIterator;
for (threadIterator = clientConnectionThread.begin(); threadIterator != clientConnectionThread.end(); threadIterator++) {
(*threadIterator).join();
}
WSACleanup();
return 0;
}
Client.cpp
#include "Client.h"
int main() {
WSADATA wsaData;
SOCKET serverSocket;
SOCKADDR_IN serverAddr;
std::cout << "client start" << std::endl;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cout << "Failed WSAStartup()" << std::endl;
}
serverSocket = socket(PROTOCOL_TYPE, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET) {
std::cout << "Failed socket()" << std::endl;
}
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = PROTOCOL_TYPE;
inet_pton(AF_INET, SERVER_IP.c_str(), &serverAddr.sin_addr);
serverAddr.sin_port = htons(SERVER_PORT);
std::cout << "connecting to server..." << std::endl;
while (true) {
if (connect(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cout << "Fail to connect server: retry in 2 seconds..." << std::endl;
Sleep(1000);
}
else {
break;
}
}
std::string sendMessage;
char recvMessage[256] = { 0, };
printf("send message to server...\n");
while (true) {
std::cout << "Write Message: ";
std::getline(std::cin, sendMessage);
send(serverSocket, sendMessage.c_str(), sendMessage.length() + 1, 0);
}
closesocket(serverSocket);
WSACleanup();
system("pause");
return 0;
}

std::Invoke, No matching overloaded function found

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.

UDP Socket programmaing c++ Recvfrom() function error

I was not able to find what I was doing wrong on the internet.
My problem is that, recvfrom() function seems to remember the last value instead of making new calls and getting my buffer updated.
I've created the same code logic with Python and it works just find but I can't find a way to do the same in C++.
So that's my code :
#define _WINSOCKAPI_
#include <windows.h>
#include <winsock2.h>
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <stdio.h>
#include <time.h>
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
int main()
{
cout << "\t\t--------------UDP Server ---------------" << endl;
cout << endl;
WSADATA WinSockData;
int iWsaStartup, iWsaCleanup;
SOCKET UDPSocketServer;
struct sockaddr_in UDPClient;
char Buffer[200];
int iBind, iReceiveFrom;
int iUDPClientLen = sizeof(UDPClient);
int iCloseSocket;
int response, offset;
ULONG cmd = 0;
iWsaStartup = WSAStartup(MAKEWORD(2, 2), &WinSockData);
if (iWsaStartup != 0) {
cout << "WSAStartup Failed" << endl;
}
cout << "WSAStartup Success" << endl;
//Setting Socket connexion information
UDPClient.sin_family = AF_INET;
UDPClient.sin_addr.s_addr = htons(INADDR_ANY);
UDPClient.sin_port = htons(40100);
//Informations to send to this address
const char* msg = "///";
size_t msg_length = sizeof(msg) - 1;
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_addr.s_addr = inet_addr("192.128.20.65");
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(40100);
//Create Socket
UDPSocketServer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (UDPSocketServer == INVALID_SOCKET) {
cout << "Socket creation failed with error : " << WSAGetLastError() << endl;
WSACleanup();
exit(0);
}
cout << "Socket creation success" << endl;
//Binding Socket to INADDR_ANY 0.0.0.0:40100
iBind = bind(UDPSocketServer, (SOCKADDR*)&UDPClient, sizeof(UDPClient));
if (iBind == SOCKET_ERROR) {
cout << "Binding failed with error : " << WSAGetLastError() << endl;
closesocket(UDPSocketServer);
WSACleanup();
exit(0);
}
cout << "Binding success" << endl;
//Make sure the socket is blocking
if (ioctlsocket(UDPSocketServer, FIONBIO, &cmd) == SOCKET_ERROR) {
cout << "ioctlsocket failed with error : " << WSAGetLastError() << endl;
}
else
cout << "ioctlsocket success : " << cmd << endl; //Return 0 because it is set for Blocking
//Send information to 192.128.20.65:40100
response = sendto(UDPSocketServer, reinterpret_cast<const char*>(msg), msg_length, 0, (sockaddr*)&myaddr, sizeof(myaddr));
if (response == SOCKET_ERROR) {
cout << "Send failed with error : " << WSAGetLastError() << endl;
}
cout << "Send success : " << response << endl;
//Wait 4 seconds
Sleep(4000);
//Send information to 192.128.20.65:40100
response = sendto(UDPSocketServer, reinterpret_cast<const char*>(msg), msg_length, 0, (sockaddr*)&myaddr, sizeof(myaddr));
if (response == SOCKET_ERROR) {
cout << "Send failed with error : " << WSAGetLastError() << endl;
}
cout << "Send success : " << response << endl;
while (1) {
//Capture receive data from any address on port 40100
//This is supose to be a blocking function but it never block after the first return call
iReceiveFrom = recvfrom(UDPSocketServer, Buffer, sizeof(Buffer) + 1, MSG_PEEK, (SOCKADDR*)&UDPClient, &iUDPClientLen);
if (iReceiveFrom == SOCKET_ERROR) {
cout << "Receive failed with error : " << WSAGetLastError() << endl;
}
else if (iReceiveFrom != 0) {
Buffer[iReceiveFrom] = '\0'; //Add end of line to Buffer
//printf("%.*s\n", iReceiveFrom, Buffer);
cout << "Receive success : " << Buffer << endl;
}
}
iCloseSocket = closesocket(UDPSocketServer);
iWsaCleanup = WSACleanup();
if (iWsaCleanup == SOCKET_ERROR) {
cout << "WSA Cleanup failed with error : " << WSAGetLastError() << endl;
}
cout << "WSA Cleanup success" << endl;
system("PAUSE");
return 0;
}
I've created a UDP C++ socket that binds itself to 0.0.0.0:40100 and listens to that port using the function recvfrom().
The problem is that my recvfrom() function seems to never update or wait for new data. It just sends over the same old data without waiting.
I've tried to add some code that will change all the value of the buffer, but when recvfrom() is called the value recieved is the same as the old one.
From what I've read, recvfrom() function is supposed to be a blocking function, but in my case, it doesn't seems to work.
I've made sure the function was blocking by looking at ioctlsocket() function response; it's set to 0, so it's supposed to block.
I've also tried to create a new socket for my sendTo() function and I got the same result.
Finally, I've also tried to remove the sendTo() functions, but like my code in Python, no data seems to comeback from the socket if I don't send the string in the first place. (Wireshark shows that there's data that is sent to this port at all the time. Without this initialization, I can't get anything to print on my socket).
I find it strange that data is recieved on a certain port on my computer but when bind to that port I can't see this data before sending data to the address that send it in the first place. So I think the problem might happens between the sendTo() call and the recvfrom().
Using MSG_PEEK with recvfrom doesn't remove the data from the incoming data queue, it's still there the next time you call recvfrom.

Winsock C++ Proxy

I'm trying to get this code to work:
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <WinSock2.h>
#pragma comment( lib, "ws2_32.lib" )
#include <Windows.h>
using namespace std;
int port = 5012;
SOCKET listen_sock;
SOCKET client_sock;
char FR_recv_buf [1048576] = "";
char recv_buf [102400] = "";
int Receive();
int Listen();
//function to initialize winsock
bool InitializeWinsock()
{
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if(iResult != 0)
{
cout << "WSAStartup failed with error: " << iResult << endl;
return false;
}
else
{
cout << "WSAStartup successfully initialized." << endl;
return true;
}
}
int ForwardResponse()
{
if (send(client_sock, FR_recv_buf, sizeof(FR_recv_buf), 0) == SOCKET_ERROR)
{
cout << "Forward Response: send() failed with error: " << WSAGetLastError() << endl;
closesocket(client_sock);
//WSACleanup();
return 0;
}
else
{
cout << "Forward Response: send() success.\n";
//go back to begginning again?
Receive();
//CreateThread(0,0,(LPTHREAD_START_ROUTINE)Receive, 0, 0 ,0);
}
}
//Function to parse hostname from http request
string ParseHostname(char * buf)
{
size_t pos;
//string to hold hostname substring
string hostname_t;
//copy request to string for easier parsing
string httpheader = buf;
pos = httpheader.find("Host: ");//find "Host: " line
hostname_t = httpheader.substr(pos + 6);//copy to substring, not including "Host: ", just the hostname
pos = hostname_t.find("\r\n");// find end of line
hostname_t.erase(pos);//erase the rest of the string which is unwanted
return hostname_t;
}
//Function to forward HTTP request from browser to webserver
int ForwardRequest()
{
int bytes_received;
SOCKADDR_IN Dest;
SOCKET frecv_sock;
hostent *Host;
//parse hostname from http request
string hostname = ParseHostname(recv_buf);
if((Host=gethostbyname(hostname.c_str()))==NULL)
{
DWORD dwError = WSAGetLastError();
if (dwError != 0)
{
if(dwError == WSAHOST_NOT_FOUND)
{
cout << "Host " << hostname.c_str() << " not found.\n";
WSACleanup();
return FALSE;
}
else if (dwError == WSANO_DATA)
{
cout << "No data record found.\n";;
WSACleanup();
return FALSE;
}
else
{
cout << "Function failed with error: " << dwError << endl;
WSACleanup();
return FALSE;
}
}
}
else
{
cout << "Successfully connected to host: " << hostname.c_str() << endl;
//privmsg(wsockdl.sock,sendbuf,curchan);
}
Dest.sin_family=AF_INET;
Dest.sin_port=htons(80);
memcpy(&Dest.sin_addr,Host->h_addr,Host->h_length);
// Create a SOCKET for connecting to server
if((frecv_sock = socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)
{
cout << "Forward Request: Error at socket(), error code: " << WSAGetLastError() << endl;
closesocket(frecv_sock);
WSACleanup();
return FALSE;
}
// Connect to server
if(connect( frecv_sock,(SOCKADDR*)&Dest,sizeof(Dest))==SOCKET_ERROR)
{
cout << "Forward Request: connect() failed, error code: " << WSAGetLastError() << endl;
closesocket( frecv_sock);
WSACleanup();
return FALSE;
}
//send intercepted request to server
if (send(frecv_sock, recv_buf, strlen(recv_buf), 0) == SOCKET_ERROR)
{
cout << "Forward Request: send() failed with error: " << WSAGetLastError() << endl;
closesocket(frecv_sock);
WSACleanup();
return 0;
}
else
{
cout << "Forward Request: send() success.\n";
}
//receive request from server
do{
bytes_received = recv(frecv_sock,FR_recv_buf,sizeof(FR_recv_buf),0);
if (bytes_received > 0){
strcat (FR_recv_buf, "\0");
cout << "Forward Request: recv() success. Bytes received: " << bytes_received << endl;
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ForwardResponse, 0 ,0 ,0);
//ForwardResponse();
}
else if ( bytes_received == 0 ){
cout << "Forward Request: Connection closed\n";
closesocket(frecv_sock);
}
else if ( bytes_received == SOCKET_ERROR){
cout << "Forward Request: recv() failed with error: " << WSAGetLastError() << endl;
closesocket(frecv_sock);
WSACleanup();
return 0;
}
}while (bytes_received > 0);
}
//Function to accept connection and receive data from browser
int Receive()
{
SOCKADDR_IN csin;
int csin_len = sizeof(csin);
int iResult;
//accept client connection
client_sock = accept(listen_sock , (LPSOCKADDR)&csin, &csin_len);//pauses here to wait for connection from client
if (client_sock == INVALID_SOCKET) {
cout << "accept failed with error: "<< WSAGetLastError() << endl;
closesocket(client_sock);
WSACleanup();
return 1;
}
else{
cout << "Client connection from IP: " << inet_ntoa(csin.sin_addr) << ":" << csin.sin_port << endl;
}
CreateThread(0, 0 , (LPTHREAD_START_ROUTINE)Receive, 0 , 0 ,0); //Start another thread to accept.
do {
iResult = recv(client_sock, recv_buf, sizeof(recv_buf), 0);
if (iResult == SOCKET_ERROR) {
closesocket(client_sock);
WSACleanup();
cout << "Receive: recv() failed with error: "<< WSAGetLastError() << endl;
}
else if (iResult > 0){
//null terminate receive buffer
//recv_buf[iResult] = '\0';
strcat(recv_buf, "\0");
cout <<"Receive: Bytes received: " << iResult << endl;
//forward HTTP request from browser to web server
cout << recv_buf << endl;
HANDLE pChildThread = CreateThread(0, 0 , (LPTHREAD_START_ROUTINE)ForwardRequest, 0 , 0 ,0);
WaitForSingleObject(pChildThread,60000); //Wait for connection between proxy and remote server
CloseHandle(pChildThread);
}
else if ( iResult == 0 ){
cout << "Receive: Connection closed\n";
}
}while ( iResult > 0 );
return 0;
}
//Function which listens for incoming connections to the proxy
int Listen()
{
SOCKADDR_IN local;
memset(&local,0,sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(port);
local.sin_addr.s_addr = INADDR_ANY;
//create socket for listening to
listen_sock = socket(AF_INET, SOCK_STREAM, 0);
//bind function associates a local address with a socket.
if (bind(listen_sock, (LPSOCKADDR)&local, sizeof(local)) == 0)
{
if (listen(listen_sock, 10) == 0)
{
cout << "Listening on: " << port << endl;
}
else
{
cout << "Error listening on socket.\n";
}
}
else{
cout << "bind() failed with error: "<< WSAGetLastError() << endl;
}
//accept and start receiving data from broswer
CreateThread(0, 0 , (LPTHREAD_START_ROUTINE)Receive, 0 , 0 ,0);
return 0;
}
int CloseServer()
{
closesocket(client_sock);
WSACleanup();
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
InitializeWinsock();
Listen();
cin.get();
return 0;
}
But it seems like the connection ends too early, or the recv() or send() functions fail. Nothing is displayed on my browser except that it couldn't connect. Can anyone spot the problem?
One major problem is that you only have one client socket. Each thread you create share the same client socket so if two connections are made before the first one is done, the first socket will be over-written with the second connection. Remember that threads share all memory in the process, including things like global variables.
Edit: Since you are using C++, why don't you encapsulate variables and functions in a class? And instead of allocating memory for buffers statically like you do, create them on the heap with new.
Edit 2
Simple multi-threaded server:
class Connection
{
public:
Connection()
: buffer(0), buffer_size(0)
{ }
void run(SOCKET sock);
privat:
SOCKET input_socket; // Socket we read from
SOCKET output_socket; // Socket we write to
char *buffer; // Buffer we read data into, and write data from
size_t buffer_size; // Total size of buffer (allocated memory)
size_t read_size; // Number of bytes read
void connect();
void recv();
void send();
};
void Connection::run(SOCKET sock)
{
input_socket = sock;
if (buffer == 0)
{
// Allocate buffer
}
// Connect to the real server
connect();
for (;;)
{
try
{
recv();
send();
}
catch (exception &e)
{
std::cerr << "Error: " << e.what() << '\n';
break;
}
}
// Clean up
delete [] buffer;
closesocket(output_socket);
closesocket(input_socket);
}
void Connection::recv()
{
// Read data into the buffer, setting "read_size"
// Like: read_size = recv(input_socket, buffer_size, 0);
// Throw exception on error (includes connection closed)
// NOTE: If error is WSAEWOULDBLOCK, set read_size to 0, don't throw exception
}
void Connection::send()
{
if (read_size > 0)
{
// Send data from the buffer
// Like: send(output_socket, buffer, read_size, 0))
// Throw exception on error
}
}
void Connection::connect()
{
// Connect to the real server
// Set the output_socket member variable
}
DWORD client_thread(LPVOID param)
{
SOCKET socket = (SOCKET) param;
// Make socket nonblocking
int mode = 1;
ioctlsocket(socket, FIONBIO, &mode)
// Main thread stuff
Connection connection;
connection.run(socket);
}
int main()
{
// Create master socket, and other initialization
for (;;)
{
SOCKET client_socket = accept(...);
CreateThread(0, 0 , (LPTHREAD_START_ROUTINE) client_thread,
(LPVOID) client_socket , 0 ,0);
}
// Clean up
}
Another major problem is that you are appending '\0' to the received buffer in the apparent expectation that send() will recognize it and stop sending from there, even though the size parameter to send() is sizeof(FR_recv_buf), which is what it will really respect. Another problem is that data items such as FR_recv_buf are instance variables instead of local variables, so you can't handle multuple concurrent connections.