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

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;
}

Related

taking multiple lines of input in C++ / WinAPI recv() function from an accepted client connection

The problem seems to be in step 8. I am trying to use a while loop on the recv() function that I thought would allow me to keep appending to the RecvBuffer, but instead it just stalls and the program doesn't do anything. I am pretty sure I am missing something that would enable me to take multiple lines of input from a connected session, say, via netcat.exe for example. Any suggestions would be very welcome.
UPDATE: I made some edits, and I can now continue to input from the client connection, and these get sent, but I get weird outputs from the previous input and clearing the buffer doesn't seem to work.
The out put I get in the Server when I input "something goes here" from
cout << "Receive success: " << RecvBuffer << " ----> end of input"<<endl;
is this:
Receive success: g goes h ----> end of input
Receive success: ere
es h ----> end of input
I'm not sure why the above occurs
#include <iostream>
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <Tchar.h>
#pragma warning(suppress : 4996)
using namespace std;
int main()
{
cout << "TCP SERVER" << endl;
//LOCAL VARIABLES
WSADATA Winsockdata;
int iWsaStartUp;
int iWsaCleanUp;
SOCKET TCPServerSocket;
int iCloseSocket;
struct sockaddr_in TCPServerAdd; //This is the structure
struct sockaddr_in TCPClientAdd;
int iTCPClientAdd = sizeof(TCPClientAdd);
int iBind;
int iListen;
SOCKET sAcceptSocket;
int iSend;
char SenderBuffer[512] = "Hello from server!";
int iSenderBuffer = strlen(SenderBuffer);
int iRecv;
char RecvBuffer[512] = "Input: ";
int iRecvBuffer = strlen(RecvBuffer) + 1;
int newiRecv;
char newRecvBuffer[512];
int newiRecvBuffer = strlen(newRecvBuffer) + 1;
//STEP 1: WSAStasrtup Function - initiates use of the Winsock DLL by a process
//See the MSDN for a great guite for this and ALL of the processes here-https://learn.microsoft.com/en-gb/windows/win32/winsock/initializing-winsock
//and https://learn.microsoft.com/en-gb/windows/win32/winsock/creating-a-basic-winsock-application
iWsaStartUp = WSAStartup(MAKEWORD(2, 2), &Winsockdata); //more info-https://stackoverflow.com/questions/24131843/what-is-makeword-used-for
if (iWsaStartUp != 0) {
cout << "WSAStartup FAILED" << endl;
}
else {
cout << "WSAStartup Success" << endl;
}
//STEP 2 - FILL THE STRUCTURE
TCPServerAdd.sin_family = AF_INET;
InetPton(AF_INET, _T("127.0.0.1"), &TCPServerAdd.sin_addr.s_addr);
//TCPServerAdd.sin_addr.s_addr = inet_addr("127.0.0.1"); <------- this is now depreciated, so see the above line of code
TCPServerAdd.sin_port = htons(8000);
//STEP 3: Create socket
TCPServerSocket = socket(AF_INET, SOCK_STREAM,0);
if (TCPServerSocket == INVALID_SOCKET) {
cout << "TCP Server socket gailed " << WSAGetLastError() << endl;
}
else {
cout << "TCP Server socket creation success" << endl;
}
//STEP 4: Bind
iBind = bind(TCPServerSocket, (SOCKADDR*)&TCPServerAdd, sizeof(TCPServerAdd));
if (iBind == SOCKET_ERROR) {
cout << "bind failed with " << WSAGetLastError() << endl;
}
else {
cout << "bind success" << endl;
}
//STEP 5: listen
iListen = listen(TCPServerSocket, SOMAXCONN);
if (iListen == SOCKET_ERROR) {
cout << "Listen function failed with " << WSAGetLastError() << endl;
}
else
{
cout << "Listen fucntiuon success" << endl;
}
//STEP 6: Accept
sAcceptSocket = accept(TCPServerSocket, (SOCKADDR*)&TCPClientAdd, &iTCPClientAdd);
if (sAcceptSocket == INVALID_SOCKET)
{
cout << "accept failed with " << WSAGetLastError() << endl;
}
else
{
cout << "Accept success" << endl;
}
//STEP 7: send
iSend = send(sAcceptSocket, SenderBuffer, iSenderBuffer, 0);
if (iSend == SOCKET_ERROR)
{
cout << "send failed with " << WSAGetLastError() << endl;
}
else
{
cout << "send success" << endl;
}
//STEP 8: recv
while (1) {
iRecv = recv(sAcceptSocket, RecvBuffer, iRecvBuffer, 0);
if (iRecv == SOCKET_ERROR)
{
cout << "receive failed with " << WSAGetLastError() << endl;
}
else
{
cout << "Receive success: " << RecvBuffer << " ----> end of input"<<endl;
}
char txbuf[512];
strcpy_s(txbuf, "you said: ");
strcat_s(txbuf, RecvBuffer);
send(sAcceptSocket, txbuf, strlen(txbuf) + 1, 0);
}
}

Function recv from browser socket, but stores nothing in buffer

I need to receive a HTTP request from my browser, when I run localhost:8228 it works fine, I receive the header in the buffer and am able to write it to the console and even echo send it back to the browser. But when I try reading a request from a actual webpage, buffer is empty, it prints nothing.
I have a simple main that looks like this:
int main (int argc, char *argv[]) {
char buffer[1024*1024] = {0};
int port_number = 8228;
if (argc == 1)
std::cout << "Using default port number, 8228." << std::endl;
else if (argc == 3) {
port_number = atoi(argv[2]);
} else {
std::cout << "::Error::" << std::endl;
std::cout << "Wrong number of arguments." << std::endl;
exit[0];
}
AppSocket app;
app.Start((int)port_number);
app.AcceptCall();
int request_size = app.ReceiveRequest(buffer, sizeof(buffer));
return 0;
}
My AppSocket functions would be:
void AppSocket::Start(int port) {
// Create a socket
listening_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listening_fd == -1) {
std::cerr << "Could not create a socket." << std::endl;
exit(-1);
}
app_hint.sin_family = AF_INET;
app_hint.sin_port = htons(port);
inet_pton(AF_INET, "127.0.0.1", &app_hint.sin_addr);
if (bind(listening_fd, (sockaddr*)&app_hint, sizeof(app_hint))< 0) {
std::cerr << "Cannot bind to IP/port." << std::endl;
exit(-2);
}
std::cout << "Socket has been bound." << std::endl;
if (listen(listening_fd, SOMAXCONN) == -1) {
std::cerr << "Cannot listen." << std::endl;
exit(-3);
}
std::cout << "Listening to port " << port << std::endl;
std::cout << "Your socket is: " << listening_fd << std::endl;
}
void AppSocket::AcceptCall() {
client_size = sizeof(client_addr);
client_fd =
accept(listening_fd, (sockaddr *)&client_addr, &client_size);
if (client_fd < 0) {
std::cerr << "Error connecting to client." << std::endl;
exit(-4);
}
std::cout << inet_ntoa(client_addr.sin_addr)
<< " connected to port "
<< ntohs(client_addr.sin_port) << std::endl;
close(listening_fd);
}
int AppSocket::ReceiveRequest(char *buffer, int max) {
std::cout << "Client is: " << client_fd << std::endl;
memset(buffer, 0, buff_size); //clear buffer
int n = recv(client_fd, buffer, buff_size, 0);
if (n < 0)
std::cerr << "A connection issue has occured." << std::endl;
if (n == 0)
std::cout << "Client disconected." << std::endl;
std::cout << "recv return " << n << std::endl;
std::cout << buffer << std::endl;
return n;
}
When I run and access a webpage I get this:
Using default port number, 8228.
Socket has been bound.
Listening to port 8228
Your socket is: 3
127.0.0.1 connected to port 37522
Client is: 4
recv return 3
None of the questions I've read seem to work for me...
edit: sorry one of the lines in the main code wasn't copied.
How can I receive repeatedly? A while loop? I tried that and just kept receiving nothing.
The code works, what was happening is that the firefox proxy settings were wrong, when I ran localhosts it worked fine because it was actually working as the server due to the port it was using but when trying to access a "real" website it didn't. After configuring it correctly it did just what it's supposed to do.

Winsock Connection C++ not connecting to either IPv4 or External Ip Address

So I have been developing something for multi-computer use (I'm working on a botnet in order to prove for a school project that computers can be easily hacked as a project for GITA) and I can't seem to make a connection with the server and client. The client can connect via 127.0.0.1, however, when attempted to connect via IPv4 or the external ip (can be found www.whatsmyip.org) it doesn't seem to work. So I have tried everything, even disabling my firewall but nothing.
I'm wondering if I happened to make a mistake in my code?
Client:
#include "client.h"
Client* Client::clientptr;
int Client::Initalize(const char* add)
{
char ownPth[MAX_PATH];
// When NULL is passed to GetModuleHandle, the handle of the exe itself is returned
HMODULE hModule = GetModuleHandle(NULL);
if (hModule != NULL)
{
// Use GetModuleFileName() with module handle to get the path
GetModuleFileName(hModule, ownPth, (sizeof(ownPth)));
std::cout << ownPth << std::endl;
}
else
{
std::cout << "Module handle is NULL" << std::endl;
}
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0)
{
std::cout << "ERROR: WINSOCK INVALID!" << std::endl;
exit(0);
}
std::cout << "Setting SOCKADDR_IN addr..." << std::endl;
addrlen = sizeof(addr);
addr.sin_addr.s_addr = inet_addr(add);
addr.sin_port = htons(4403);
addr.sin_family = AF_INET;
connection = socket(AF_INET, SOCK_STREAM, NULL);
while (true)
{
std::cout << "Attempting connection..." << std::endl;
if (connect(connection, (SOCKADDR*)&addr, addrlen) > 0 || connect == 0)
{
std::cout << "Connection established!" << std::endl;
break;
}
std::cout << "Error: Failed to connect! Retrying... " << std::endl;
Sleep(1000);
}
clientptr = this;
return 0;
}
int Client::Run()
{
std::cout << std::endl << "Running..." << std::endl;
while (true)
{
Sleep(10);
}
return 0;
}
Server:
#include "server.h"
Server* Server::serverptr; //Serverptr is necessary so the static ClientHandler method can access the server instance/functions.
int Server::Initalize()
{
std::cout << "Setting crash handler..." << std::endl;
std::cout << "Looking at winsock dll version..." << std::endl;
WSADATA wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0)
{
MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
exit(1);
}
std::cout << "Creating listening socket..." << std::endl;
addrlen = sizeof(addr);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(4403);
addr.sin_family = AF_INET;
std::cout << "The socket data addr "
<< "{"
<< "addr.sin_addr.s_addr = " << addr.sin_addr.s_addr
<< ", addr.sin_port = " << addr.sin_port
<< ", addr.sin_family = " << addr.sin_family
<< "}" << std::endl;
sListen = socket(AF_INET, SOCK_STREAM, NULL); //Create socket to listen for new connections
if (bind(sListen, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) //Bind the address to the socket, if we fail to bind the address..
{
std::string ErrorMsg = "Failed to bind the address to our listening socket. Winsock Error:" + std::to_string(WSAGetLastError());
MessageBoxA(NULL, ErrorMsg.c_str(), "Error", MB_OK | MB_ICONERROR);
exit(1);
}
if (listen(sListen, SOMAXCONN) == SOCKET_ERROR) //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Oustanding Max connections, if we fail to listen on listening socket...
{
std::string ErrorMsg = "Failed to listen on listening socket. Winsock Error:" + std::to_string(WSAGetLastError());
MessageBoxA(NULL, ErrorMsg.c_str(), "Error", MB_OK | MB_ICONERROR);
exit(1);
}
std::cout << "Finalizing..." << std::endl;
output = false;
currClient = 0;
std::cout << "Setting serverptr..." << std::endl;
serverptr = this;
std::cout << "Creating Threads..." << std::endl;
serverptr->Listening = false;
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)Listen, NULL, NULL, NULL); //Create thread that will manage all outgoing packets
while (serverptr->Listening == false);
std::cout << "Done Initalizing!" << std::endl << std::endl;
return 0;
}
int Server::Run()
{
std::cout << "Running server...";
serverptr->Listening = true;
while (true)
{
std::string userinput;
int inputInt;
HANDLE hConsoe = GetStdHandle(STD_OUTPUT_HANDLE);
while (true)
{
std::cout << std::endl << "] ";
std::getline(std::cin, userinput);
serverptr->HandleInput(userinput);
}
}
return 0;
}
void Server::Listen()
{
if (serverptr->output)
std::cout << "Listener socket running..." << std::endl;
serverptr->Listening = true;
while (true)
{
if (serverptr->Listening == true)
{
SOCKET newConnection //the connection for the socket
= accept(serverptr->sListen, (SOCKADDR*)&serverptr->addr, &serverptr->addrlen); //Accept a new connection
if (newConnection == 0)
{
if (serverptr->output)
std::cout << "FAILED TO ACCEPT THE CLIENTS CONNECTION!" << std::endl;
}
else
{
if (serverptr->output)
{
std::cout << "A connection has been made [" << inet_ntoa(serverptr->addr.sin_addr) << "]!" << std::endl;
std::cout << "Creating Client(" << newConnection << ")..." << std::endl;
}
Client newClient(newConnection, serverptr->addr);
int connectionId = serverptr->clients.size();
serverptr->clients.push_back(newClient);
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)RecvClient, NULL, NULL, NULL); //Create thread that will manage all incomming packets
int index = serverptr->clients.size() - 1;
while (!serverptr->clients[index].Listening);
if (serverptr->output)
std::cout << "Client success [" << (index + 1) << "]!" << std::endl;
}
}
}
return;
}
void Server::RecvClient()
{
int index = serverptr->clients.size() - 1;
char data[1600];
if (serverptr->output)
std::cout << "Listening for client[" << (index + 1) << "]..." << std::endl;
serverptr->clients[index].Listening = true;
while (true)
{
recv(serverptr->clients[index]._socket, data, sizeof(data), 0);
if (serverptr->output)
std::cout << "Data Recieved from client[" << (index + 1) << "]!" << std::endl;
if ((int)data[0] < 0)
{
if (serverptr->output)
std::cout << "Client [" << (index + 1) << "] is disconnecting with the current code {" << (int)data[0] << "}..." << std::endl;
serverptr->DisconnectClient(index);
break;
}
}
if (serverptr->output)
std::cout << "No longer listening for client[" << (index + 1) << "]!" << std::endl;
}
void Server::HandleInput(std::string string)
{
std::string sHandle = string;
std::istringstream iss(string);
std::vector<std::string> sTokens((std::istream_iterator<std::string>(iss)),
std::istream_iterator<std::string>());
if (sHandle == "cls")
{
system("cls");
return;
}
if (sHandle == "list")
{
int index = serverptr->clients.size() - 1;
std::cout << "Total Clients: " << serverptr->clients.size() << std::endl;
for (int i = 0; i < serverptr->clients.size(); i++)
{
std::cout << (char)195 << (char)196 << " Client [" << i + 1 << "] {" << serverptr->clients[i]._socket << ", " << inet_ntoa(serverptr->clients[i]._address.sin_addr) << "}" << std::endl;
}
return;
}
if (sHandle == "data")
{
std::cout << "Toggling data output..." << std::endl;
serverptr->output = true;
return;
}
if (sTokens[0] == "broadcast")
{
int change = 0;
std::cout << "Toggling client: ";
if (sTokens.size() > 1)
{
std::stringstream strings(sTokens[1]);
strings >> change;
if (change > serverptr->clients.size())
{
change = serverptr->clients.size();
}
}
if (change > 0) std::cout << change << std::endl;
else std::cout << "All" << std::endl;
serverptr->currClient = change;
return;
}
std::cout << "Error: Unknown command!" << std::endl;
return;
}
void Server::DisconnectClient(int id)
{
if (serverptr->output)
std::cout << "void Server::DisconnectClient(" << id << ")..." << std::endl;
closesocket(serverptr->clients[id]._socket);
serverptr->clients.erase(serverptr->clients.begin() + (id));
return;
}
Client::Client(SOCKET socket, SOCKADDR_IN address)
{
this->_address = address;
this->_socket = socket;
this->Listening = false;
}

Winsock simple Client Server, receive fails

I am trying to run this simple server client program's using winsock. Server is accepting the clients connection, but is unable to receive the data client sends. I am struggling to find the problem.
SERVER :
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#define DEFAULT_PORT 18000
int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s, new_socket;
struct sockaddr_in server, client;
char *message, client_msg[2000];
int port, c, recv_size;
if (argc > 2)
{
std::cout << "usage : " << argv[1] << " <PORT>\n";
std::cout << "If no port is given then default port is used.\n";
std::cout << "DEFAULT PORT : 18000\n";
return 1;
}
if (argc == 2)
{
port = atoi(argv[2]);
}
else
{
port = DEFAULT_PORT;
}
std::cout << "Initializing Winsock...";
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
std::cout << "Failed. Error code" << WSAGetLastError();
return 1;
}
std::cout << "Initialized.\n\n";
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
std::cout << "Could not create Socket : " << WSAGetLastError() << "\n";
return 1;
}
std::cout << "Socket Created.\n";
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
std::cout << "Bind failed with error code : " << WSAGetLastError() << "\n";
}
std::cout << "Bind done.\n";
listen(s, 3);
std::cout << "Waiting for incoming connections...\n";
while (true)
{
c = sizeof(struct sockaddr_in);
new_socket = accept(s, (struct sockaddr*)&client, &c);
if (new_socket == INVALID_SOCKET)
{
closesocket(new_socket);
std::cout << "Accept failed with error code : " << WSAGetLastError() << "\n";
}
else
{
std::cout << "Connection accepted.\n";
if ((recv_size = recv(s, client_msg, 200, 0)) == SOCKET_ERROR)
{
closesocket(new_socket);
std::cout << "Receive Failed.\n\n";
}
else
{
if (strcmp(client_msg, "PASSWD"))
{
message = "HELLO!";
send(new_socket, message, strlen(message), 0);
}
else
{
message = "Authentication failed!";
send(new_socket, message, strlen(message), 0);
closesocket(new_socket);
}
}
}
}
closesocket(s);
WSACleanup();
return 0;
}
CLIENT:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#define DEFAULT_SERVER "127.0.0.1"
#define DEFAULT_PORT 18000
#define PASSWORD "PASSWD"
int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
char *message, server_reply[2000], *server_addr;
int recv_size, port = DEFAULT_PORT;
if (argc > 4)
{
std::cout << "usage : " << argv[0] << " <Server IP> <Server Port> [DATA]\n\n";
std::cout << "If any argument is missing, default values will be used.\n";
std::cout << "Default Address : localhost (127.0.0.1)\nDefault Port : 18000\nDefault DATA: 'PASSWD'\n\n";
return 1;
}
else if (argc == 4)
{
server_addr = argv[1];
port = atoi(argv[2]);
message = argv[3];
}
else if (argc == 3)
{
server_addr = argv[1];
port = atoi(argv[2]);
message = PASSWORD;
}
else if (argc == 2)
{
server_addr = argv[1];
port = DEFAULT_PORT;
message = PASSWORD;
}
else
{
server_addr = DEFAULT_SERVER;
port = DEFAULT_PORT;
message = PASSWORD;
//server_addr = "127.0.0.1";
//port = 2222;
//message = "HELLO";
}
std::cout << "Initialising Winsock..\n";
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
std::cout << "Failed.. Error Code : " << WSAGetLastError() << "\n";
return 1;
}
std::cout << "Winsock Initialised.\n";
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
std::cout << "Could not create socket : " << WSAGetLastError() << "\n";
}
std::cout << "Socket Created.\n";
server.sin_addr.s_addr = inet_addr(server_addr);
server.sin_family = AF_INET;
server.sin_port = htons(port);
if (connect(s, (struct sockaddr*)&server, sizeof(server)) < 0)
{
std::cout << "Could not connect to " << server_addr << " on port " << port << ".\n";
WSACleanup();
return 1;
}
std::cout << "Connected to " << server_addr << " on port " << port << ".\n\n";
if (send(s, message, strlen(message), 0) < 0)
{
std::cout << "Sending Data failed.\n";
WSACleanup();
return 1;
}
std::cout << "Data send.\n\n";
//Sleep(500);
if ((recv_size = recv(s, server_reply, 20, 0)) == SOCKET_ERROR )
{
std::cout << "Receive Failed.\n\n";
}
else
{
server_reply[recv_size] = '\0';
std::cout << server_addr << " : " << server_reply << "\n";
}
//Sleep(5000);
closesocket(s);
WSACleanup();
return 0;
}
Any help would be appreciated. Thanks.
if ((recv_size = recv(s, client_msg, 200, 0)) == SOCKET_ERROR)
Change s to new_socket in your server side code.

Winsock single client server send and receive simultaneously

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;
}