Reputation: 135
Im trying to do multi client chat in c++ using TCP socket. i have download the source of the socket implementation from this site.
The problem is when i try to send message to the server from the client, the "ecko" that i recive from the server is endless string of spaces.
i tried to debug the client code, the client read the input properly. In the first few message the server send back to the client his message, but after few messages the client get back endless spaces. i tried to use memset to nullify(put zero in all the array), but its making it worse, the server dont recive messages at all.
Would appreciate help (:
This is the server side:
#include "PracticalSocket.h"
#include <stdio.h>
#include <process.h>
#include <Windows.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
TCPSocket* MyClients[20];
int ClientCount = 0;
void connectCLient(void* pValue){
int nI,Flag;
char st[1024];
//memset(st,0,1024); // doing problems
TCPSocket* pServerClient = (TCPSocket*)pValue;
MyClients[ClientCount] = pServerClient;
ClientCount++;
try{
while (true)
{
Flag = pServerClient->recv(st,strlen(st));
if(Flag>1){
printf("%s\n",st);
for(nI = 0; nI< ClientCount ; nI++){
MyClients[nI]->send(st,strlen(st)+1);
}
}
}
}
catch(...){
puts("one client lefttt");
}
}
int main(int argc, char* argv[])
{
TCPServerSocket* pServer = new TCPServerSocket(8546);
int nClientCounter = 0;
printf("Start TCP Server ... on Port %d\n", 8546);
try{
while(true)
{
printf("Wait for new TCP Clients ... \n");
TCPSocket* pClient = pServer->accept();
_beginthread(connectCLient,0,(void*)pClient);
printf("Client %d Connected ... \n", ++nClientCounter);
}
}
catch(...){
puts("one client left");
}
return 0;
}
This is the Client side:
#include "PracticalSocket.h"
#include <stdio.h>
#include <process.h>
#include <Windows.h>
using namespace std;
#pragma comment (lib, "ws2_32.lib")
void ReciveMessages(void * pValue ){
char recvM[1024];
TCPSocket* pClient = (TCPSocket*)pValue;
while(true){
pClient->recv(recvM,strlen(recvM));
printf("%s\n",recvM);
}
}
int main(int argc, char* argv[])
{
try
{
TCPSocket * cClient = new TCPSocket();
cClient->connect("127.0.0.1",8546);
_beginthread(ReciveMessages,0,(void*)cClient);
char st[1024];
memset(st,0,1024);
while(true)
{
printf("Press Text -->");
fgets(st, sizeof st, stdin);
cClient->send(st,strlen(st)+2);
}
}
catch(...)
{
printf("Socket Error..!");
system("pause");//run cmd comment - stop the system
}
return 0;
}
Upvotes: 1
Views: 2596
Reputation: 136505
There are a few mistakes in the code:
MyClients[ClientCount] = pServerClient;
ClientCount++;
Since the above happens in different threads, ClientCount++
is non-atomic and causes race conditions. Make ClientCount
atomic or do that in one server thread.
In:
Flag = pServerClient->recv(st,strlen(st));
if(Flag>1) {
printf("%s\n",st);
for(nI = 0; nI< ClientCount ; nI++)
MyClients[nI]->send(st,strlen(st)+1);
st
doesn't end with \0
, because it can be a partial read, so that strlen(st)
returns wrong results. Fix:
ssize_t received = pServerClient->recv(st, sizeof st - 1);
if(received > 0) {
st[received] = 0; // Zero-terminate.
printf("%s\n", st);
for(nI = 0; nI< ClientCount ; nI++)
MyClients[nI]->send(st, received);
Similar issue:
pClient->recv(recvM,strlen(recvM));
printf("%s\n",recvM);
Fix:
ssize_t received = pClient->recv(recvM, sizeof recvM - 1);
if(received > 0) {
recvM[received] = 0;
printf("%s\n",recvM);
}
And in:
cClient->send(st,strlen(st)+2);
No point in sending the zero terminator:
cClient->send(st, strlen(st));
TCP is a stream protocol which means that send
and recv
may send/receive partial data and there are no message boundaries. You may like to delimit your messages.
Upvotes: 1