I'm trying to write a server for a client/server chat program.
The only problem is that if once client disconnects, the server starts spamming their last message to the server. Even if they reconnect, it keeps spamming..I've tried googling, but I can't find anything.
Here's the Server Code:
#include "MasterServer.h"
using namespace std;
SOCKADDR_IN Server;
int addrlen = sizeof(Server);
SOCKET sListen;
SOCKET Connect;
SOCKET* Connections;
int port = 444;
int ConCounter = 0;
char* Recv = new char[256];
int ServerThread(int ID)
{
ZeroMemory(Recv, sizeof(Recv));
for(;;)
{
if(recv(Connections[ID],Recv ,256 ,NULL))
{
cout << Recv << endl;
}
}
}
int InitWinSock()
{
int RetVal = 0;
WSAData wsa;
WORD Version = MAKEWORD(2,1);
RetVal = WSAStartup(Version, &wsa);
return RetVal;
}
int main()
{
int RetVal = 0;
RetVal = InitWinSock();
if(RetVal != 0)
{
cout << "WinSock Start Up Failure";
}
Connections = (SOCKET*)calloc(64, sizeof(SOCKET));
sListen = socket(AF_INET, SOCK_STREAM, NULL);
Connect = socket(AF_INET, SOCK_STREAM, NULL);
cout << "\t\t----====ModernBacon Server====----"<< endl;
cout << "What Port Would You Like To Run On [Default 444]: ";
cin >> port;
system("cls");
Server.sin_addr.s_addr = inet_addr("127.0.0.1");
Server.sin_family = AF_INET;
Server.sin_port = htons(port);
bind(sListen, (SOCKADDR*)&Server, sizeof(Server));
//Listening
listen(sListen, 64);
cout << "Listening For Connections IP:"<<inet_ntoa(Server.sin_addr);"Port:"<<port<<
endl;
for(;;)
{
if(Connect = accept(sListen, (SOCKADDR*)&Server, &addrlen))
{
Connections[ConCounter] = Connect;
char* ID = new char[64];
ZeroMemory(ID, sizeof(ID));
itoa(ConCounter, ID, 10);
send(Connections[ConCounter], ID, sizeof(ID),NULL);
ConCounter = ConCounter + 1;
CreateThread(NULL,NULL, (LPTHREAD_START_ROUTINE)
ServerThread, (LPVOID)(ConCounter -1), NULL, NULL);
cout << "\t\tClient Connected!\tID: " <<
ConCounter << endl;
}
}
return(0);
}
I have no clue whats going on...
There are quite a few problems with your code. Try something more like this instead:
#include "MasterServer.h"
#include <string>
using namespace std;
static const int MAX_CLIENTS = 64;
static const int MAX_RECV = 256;
struct ClientInfo
{
int ID;
SOCKET Connection;
char Recv[MAX_RECV];
};
ClientInfo Clients[MAX_CLIENTS];
DWORD WINAPI ServerThread(LPVOID lpParam)
{
ClientInfo *Client = (ClientInfo*) lpParam;
char szID[64] = {0};
itoa(Client->ID, szID, 10);
int RetVal = send(Client->Connection, szID, sizeof(szID), NULL);
if (RetVal != sizeof(szID))
{
cout << "Client " << Client->ID << " Send Failure. Error " << WSAGetLastError() << endl;
}
else
{
do
{
RetVal = recv(Client->Connection, Client->Recv, MAX_RECV, NULL);
if (RetVal == SOCKET_ERROR)
{
cout << "Client " << Client->ID << " Recv Failure. Error " << WSAGetLastError() << endl;
break;
}
if (RetVal == 0)
{
cout << "Client " << Client->ID << " disconnected" << endl;
break;
}
cout << "Client " << Client->ID << ": " << string(Client->Recv, RetVal) << endl;
}
while (true);
}
closesocket(Client->Connection);
Client->Connection = INVALID_SOCKET;
return 0;
}
int InitWinSock()
{
WSAData wsa;
return WSAStartup(MAKEWORD(2,1), &wsa);
}
int main()
{
SOCKADDR_IN addr;
int addrlen;
SOCKET sListen;
SOCKET sClient;
int port = 444;
int index;
cout << "\t\t----====ModernBacon Server====----"<< endl;
for (int i = 0; i < MAX_CLIENTS; ++i)
Connections[i] = INVALID_SOCKET;
int RetVal = InitWinSock();
if (RetVal != 0)
{
cout << "WinSock Start Up Failure. Error " << RetVal << endl;
return 0;
}
sListen = socket(AF_INET, SOCK_STREAM, NULL);
if (sListen == INVALID_SOCKET)
{
cout << "WinSock Socket Failure. Error " << WSAGetLastError() << endl;
return 0;
}
cout << "What Port Would You Like To Run On [Default 444]: ";
cin >> port;
system("cls");
ZeroMemory(&addr, sizeof(addr));
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
RetVal = bind(sListen, (SOCKADDR*)&addr, sizeof(addr));
if (RetVal != 0)
{
cout << "WinSock Bind Failure. Error " << WSAGetLastError() << endl;
return 0;
}
//Listening
RetVal = listen(sListen, MAX_CLIENTS);
if (RetVal != 0)
{
cout << "WinSock Listen Failure. Error " << WSAGetLastError() << endl;
return 0;
}
cout << "Listening For Connections. IP: " << inet_ntoa(addr.sin_addr) << ", Port: " << port << endl;
do
{
addrlen = sizeof(addr);
sClient = accept(sListen, (SOCKADDR*)&addr, &addrlen);
if (sClient == INVALID_SOCKET)
{
cout << "WinSock Accept Failure. Error " << WSAGetLastError() << endl;
return 0;
}
index = -1;
for (int i = 0; i < MAX_CLIENTS; ++i)
{
if (Clients[i].Connection == INVALID_SOCKET)
{
index = i;
break;
}
}
if (index == -1)
{
closesocket(sClient);
cout << "\t\tClient Connected. Max Clients Exceeded!" << endl;
continue;
}
Clients[index].ID = index + 1;
Clients[index].Connection = sClient;
CreateThread(NULL, NULL, &ServerThread, &Clients[index], NULL, NULL);
cout << "\t\tClient Connected!\tID: " << Clients[index].ID << endl;
}
while (true);
return 0;
}
Related
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.
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);
}
void TCPConnectionV5::startServer()
{
/* Initialize Winsock */
int start;
sockaddr_in SERVER;
SERVER.sin_family = AF_INET;
SERVER.sin_addr.s_addr = INADDR_ANY;
//SERVER.sin_port = htons(stoi(DEFAULT_PORT));
SERVER.sin_port = htons(1787);
start = WSAStartup(MAKEWORD(2, 2), &_wsaData);
if (start != 0)
{
cout << "Error on WSAStartup: " << start << endl;
}
/* Create socket that will connect to server */
_listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
_socketCollection.push_back(_listener);
if (_listener == INVALID_SOCKET)
{
cout << "Error creating socket to connect to server: " << WSAGetLastError() << endl;
WSACleanup();
}
/* Bind the socket */
start = bind(_listener, (sockaddr*)&SERVER, sizeof(SERVER));
if (start == SOCKET_ERROR)
{
cout << "Error on bind:" << WSAGetLastError() << endl;
closesocket(_listener);
WSACleanup();
}
/* Create the listener socket */
start = listen(_listener, 16);
if (start == SOCKET_ERROR)
{
cout << "Error on entering the listening state: " << start << endl;
closesocket(_listener);
WSACleanup();
}
printTime();
cout << "Server entered listening state" << endl;
/* Create the thread */
sockaddr_in client;
int clientSize = sizeof(client);
while (true)
{
SOCKET messager = accept(_listener, (struct sockaddr*)&client, &clientSize);
_socketCollection.push_back(messager);
locker.lock();
printTime();
if (messager != SOCKET_ERROR)
{
cout << "Client Connection success!" << endl;
cout << "Messager: " << messager << endl;
locker.unlock();
std::thread newThread([&] {this->exchange(messager); });
newThread.detach();
}
else
{
locker.unlock();
}
}
}
DWORD TCPConnectionV5::exchange(SOCKET messager)
{
int bytesSent = sendMessage(messager, msg);
if (bytesSent <= 0)
{
closesocket(messager);
return -1;
}
int bytesReceived = receiveMessage(messager);
if (bytesReceived <= 0)
{
closesocket(messager);
return -1;
}
}
I noticed that when the server connects with multiple clients, that there sometimes appear to be duplicate messages that send to some clients, which is accompanied by missing messages to another client application. I have mutex lock/unlock in place for sending/receiving messages, but what's causing these duplicate/missing messages? Is there some underlying issue I have to address regarding the threads?
I am writing for the first time in this language and could only write this
UDP server and client. I need help; I want to server waits for a response and displays it. If within 5 sec. the answer is not received, the program starts its execution again.If you don't understand task, you can translate task(fifth) :https://www.opennet.ru/docs/RUS/socket/node15.html
#include <iostream>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
void main()
{
struct timeval tv;
fd_set fd;
WSADATA data;
WORD version = MAKEWORD(2, 2);
int wsOk = WSAStartup(version, &data);
cout << "Server opened" << endl;
if (wsOk != 0)
{
cout << "Can't start Winsock! " << wsOk;
return;
}
SOCKET in = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in serverHint;
serverHint.sin_addr.S_un.S_addr = ADDR_ANY;
serverHint.sin_family = AF_INET;
serverHint.sin_port = htons(54000);
if (bind(in, (sockaddr*)& serverHint, sizeof(serverHint)) == SOCKET_ERROR)
{
cout << "Can't bind socket! " << WSAGetLastError() << endl;
return;
}
sockaddr_in client;
int clientLength = sizeof(client);
char buf[1024];
while (true)
{
FD_ZERO(&fd);
FD_SET(in, &fd);
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(0, &fd, NULL, NULL, &tv) > 0)
{
ZeroMemory(&client, clientLength);
ZeroMemory(buf, 1024);
int bytesIn = recvfrom(in, buf, 1024, 0, (sockaddr*)& client, &clientLength);
if (bytesIn == SOCKET_ERROR)
{
cout << "Error receiving from client " << WSAGetLastError() << endl;
continue;
}
char clientIp[256];
ZeroMemory(clientIp, 256);
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);
cout << "Message recv from " << clientIp << " : " << buf << endl;
}
else {
cout << "Timeout" << endl;
closesocket(in);
break;
}
closesocket(in);
WSACleanup();
}
}
Translation of the task by google translate:
Write a program that asks the user for an IP address, port number and text string,
sends a string to the specified address using the UDP protocol,
waits for a response, and displays it on the screen.
If within 5 sec. the answer is not received, the program starts its execution again.
Your program is completely missing part 1 and 2 so you must add those.
For part 3, move your current while loop so it covers everything in main:
int main() // note: main must be declared to return 'int'
{
while(true) { // new start of the while loop, first in main
// ... your current code until the below line ...
cout << "Message recv from " << clientIp << " : " << buf << endl;
// exit program if you've received a response
closesocket(in);
break; // break out of while loop
}
else {
cout << "Timeout" << endl;
}
closesocket(in);
WSACleanup();
} // end of while loop
WSACleanup();
} // end of main
This reinitializer Winsock2 for every try which is unnecessary and it also has closesocket in multiple places. I would add classes for both WSAStartup/WSACleanup and socket/closesocket to manage the resources they have acquire.
#include <iostream>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
void main()
{
struct timeval tv;
fd_set fd;
WSADATA data;
WORD version = MAKEWORD(2, 2);
int wsOk = WSAStartup(version, &data);
cout << "5" << endl;
if (wsOk != 0)
{
cout << "Winsock" << wsOk;
return;
}
SOCKET in = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in serverHint;
serverHint.sin_addr.S_un.S_addr = ADDR_ANY;
serverHint.sin_family = AF_INET;
serverHint.sin_port = htons(54000);
if (bind(in, (sockaddr*)& serverHint, sizeof(serverHint)) == SOCKET_ERROR)
{
cout << "hhhh" << WSAGetLastError() << endl;
return;
}
sockaddr_in client;
int clientLength = sizeof(client);
char buf[1024];
while (true)
{
FD_ZERO(&fd);
FD_SET(in, &fd);
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(0, &fd, NULL, NULL, &tv) > 0)
{
ZeroMemory(&client, clientLength);
ZeroMemory(buf, 1024);
int bytesIn = recvfrom(in, buf, 1024, 0, (sockaddr*)& client, &clientLength);
if (bytesIn == SOCKET_ERROR)
{
cout << "EEEROOR" << WSAGetLastError() << endl;
continue;
}
char clientIp[256];
ZeroMemory(clientIp, 256);
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);
cout << "ะก " << clientIp << " : " << buf << endl;
closesocket(in);
WSACleanup();
exit(0);
}
else {
cout << "jhkjhkjhjn" << endl;
closesocket(in);
main();
}
}
}
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.