Through a tutorial I was able to built a C++ client application that connects to a server and is able to send and receive data.
Currently the application ends after it receives a string from the server. What I want to do is to let the client keep listening for incoming data.
Currently a part of my code looks like this:
string tcp_client::receive(int size=512)
{
char buffer[size];
string reply;
//Receive a reply from the server
if( recv(sock , buffer , sizeof(buffer) , 0) < 0)
{
puts("recv failed");
}
reply = buffer;
return reply;
}
int main(int argc , char *argv[])
{
tcp_client c;
string host;
cout<<"Enter hostname : ";
cin>>host;
c.conn(host , 4004);
//send some data
c.send_data("TEST STRING \n\r\n");
//receive and echo reply
// (want to keep listening here for data)
cout<<c.receive(1024);
//done
return 0;
}
I don't want the client to end but I want it to keep listening for data. I'm thinking about adding this code:
while(buffer = c.receive(1024))
{
// do something with buffer ... switch/case construction
// After that, start listening again
}
First of all I'm not sure if this works. But second, I'm also not sure if it's smart to put in a never ending while loop in there (never ending, until I terminate the application of course).
Can I simply put in a while loop like that? Or are there other. better methods to make a client application keep listening for data?
You should check if you at a certain point you receive 0 bytes , which means that the other end has closed the connection and is not going to send anymore. That means that you can close your socket too and close the application.
Under normal condition , when the server is also running, receive is a blocking call, it just hangs there until there is something received.
Now if the server closes the connection you really must exit the endless loop or you will continuously call receive on a socket that is closed which will return immediately taking a lot of load on your cpu.
All programs should generally take care of the error conditions or unexpected behavior can occur.
Yes you should put receive in a loop. But you should know that the receive call will block your program until it finds any data. That means if you are working with a GUI, your GUI will halt until the receive will unblock the program. For console application its ok..
Related
[TL;DR version: the code below hangs indefinitely on the second recv() call both in Release and Debug mode. In Debug, if I place or remove a breakpoint anywhere in the code, it makes the execution continue and everything behaves normally]
I'm coding a simple client-server communication using UNIX sockets. The server is in C++ while the client is in python. The connection (TCP socket on localhost) gets established no problem, but when it comes to receiving data on the server side, it hangs on the recv function. Here is the code where the problem happens:
bool server::readBody(int csock) // csock is the socket filedescriptor
{
int bytecount;
// protobuf-related variables
google::protobuf::uint32 siz;
kinMsg::request message;
// if the code is working, client will send false
// I initialize at true to be sure that the message is actually read
message.set_endconnection(true);
// First, read 4-characters header for extracting data size
char buffer_hdr[5];
if((bytecount = recv(csock, buffer_hdr, 4, MSG_WAITALL))== -1)
::std::cerr << "Error receiving data "<< ::std::endl;
buffer_hdr[4] = '\0';
siz = atoi(buffer_hdr);
// Second, read the data. The code hangs here !!
char buffer [siz];
if((bytecount = recv(csock, (void *)buffer, siz, MSG_WAITALL))== -1)
::std::cerr << "Error receiving data " << errno << ::std::endl;
//Finally, process the protobuf message
google::protobuf::io::ArrayInputStream ais(buffer,siz);
google::protobuf::io::CodedInputStream coded_input(&ais);
google::protobuf::io::CodedInputStream::Limit msgLimit = coded_input.PushLimit(siz);
message.ParseFromCodedStream(&coded_input);
coded_input.PopLimit(msgLimit);
if (message.has_endconnection())
return !message.endconnection();
return false;
}
As can be seen in the code, the protocol is such that the client will first send the number of bytes in the message in a 4-character array, followed by the protobuf message itself. The first recv call works well and does not hang. Then, the code hangs on the second recv call, which should be recovering the body of the message.
Now, for the interesting part. When run in Release mode, the code hangs indefinitely and I have to kill either the client or the server. It does not matter whether I run it from my IDE (qtcreator), or from the CLI after a clean build (using cmake/g++).
When I run the code in Debug mode, it also hangs at the same recv() call. Then, if I place or remove a breakpoint ANYWHERE in the code (before or after that line of code), it starts again and works perfectly : the server receives the data, and reads the correct message.endconnection() value before returning out of the readBody function. The breakpoint that I have to place to trigger this behavior is not necessarily trigerred. Since the readBody() function is in a loop (my C++ server waits for requests from the python client), at the next iteration, the same behavior happens again, and I have to place or remove a breakpoint anywhere in the code, which is not necessarily triggered, in order to go past that recv() call. The loop looks like this:
bool connection = true;
// server waiting for client connection
if (!waitForConnection(connectionID)) std::cerr << "Error accepting connection" << ::std::endl;
// main loop
while(connection)
{
if((bytecount = recv(connectionID, buffer, 4, MSG_PEEK))== -1)
{
::std::cerr << "Error receiving data "<< ::std::endl;
}
else if (bytecount == 0)
break;
try
{
if(readBody(connectionID))
{
sendResponse(connectionID);
}
// if client is requesting disconnection, break the while(true)
else
{
std::cout << "Disconnection requested by client. Exiting ..." << std::endl;
connection = false;
}
}
catch(...)
{
std::cerr << "Erro receiving message from client" << std::endl;
}
}
Finally, as you can see, when the program returns from readBody(), it sends back another message to the client, which processes it and prints in the standard output (python code working, not shown because the question is already long enough). From this last behavior, I can conclude that the protocol and client code are OK. I tried to put sleep instructions at many points to see whether it was a timing problem, but it did not change anything.
I searched all over Google and SO for a similar problem, but did not find anything. Help would be much appreciated !
The solution is to not use any flags. Call recv with 0 for the flags or just use read instead of recv.
You are requesting the socket for data that is not there. The recv expects 10 bytes, but the client only sent 6. The MSG_WAITALL states clearly that the call should block until 10 bytes are available in the stream.
If you dont use any flags, the call will succeed with a bytecount at 6, which is the exact same effect than with MSG_DONTWAIT, without the potential side effects of non-blocking calls.
I did the test on the github project, it works.
The solution is to replace MSG_WAITALL by MSG_DONTWAIT in the recv() calls. It now works fine. To summarize, it makes the recv() calls non blocking, which makes the whole code work fine.
However, this still raises many questions, the first of which being: why was it working with this weird breakpoint changing thing ?
If the socket was blocking in the first place, one could assume that it is because there is no data on the socket. Let's assume both situations here :
There is no data on the socket, which is the reason why the blocking recv() call was not working. Changing it to a non blocking recv() call would then, in the same situation, trigger an error. If not, the protobuf deserialization would afterwards fail trying to deserialize from an empty buffer. But it does not ...
There is data on the socket. Then, why on earth would it block in the first place ?
Obviously there is something that I don't get about sockets in C, and I'd be very happy if somebody has an explanation for this behavior !
I was following a tutorial on youtube on building a chat program using winsock and c++. Unfortunately the tutorial never bothered to consider race conditions, and this causes many problems.
The tutorial had us open a new thread every time a new client connected to the chat server, which would handle receiving and processing data from that individual client.
void Server::ClientHandlerThread(int ID) //ID = the index in the SOCKET Connections array
{
Packet PacketType;
while (true)
{
if (!serverptr->GetPacketType(ID, PacketType)) //Get packet type
break; //If there is an issue getting the packet type, exit this loop
if (!serverptr->ProcessPacket(ID, PacketType)) //Process packet (packet type)
break; //If there is an issue processing the packet, exit this loop
}
std::cout << "Lost connection to client ID: " << ID << std::endl;
}
When the client sends a message, the thread will process it and send it by first sending packet type, then sending the size of the message/packet, and finally sending the message.
bool Server::SendString(int ID, std::string & _string)
{
if (!SendPacketType(ID, P_ChatMessage))
return false;
int bufferlength = _string.size();
if (!SendInt(ID, bufferlength))
return false;
int RetnCheck = send(Connections[ID], _string.c_str(), bufferlength, NULL); //Send string buffer
if (RetnCheck == SOCKET_ERROR)
return false;
return true;
}
The issue arises when two threads (Two separate clients) are synchronously trying to send a message at the same time to the same ID. (The same third client). One thread may send to the client the int packet type, so the client is now prepared to receive an int, but then the second thread sends a string. (Because the thread assumes the client is waiting for that). The client is unable to process correctly and results in the program being unusable.
How would I solve this issue?
One solution I had:
Rather than allow each thread to execute server commands on their own, they would set an input value. The main server thread would loop through all the input values from each thread and then execute the commands one by one.
However I am unsure this won't have problems of its own... If a client sends multiple messages in the time frame of a single server loop, only one of the messages will send (since the new message would over-write the previous message). Of course there are ways around this, such as arrays of input or faster loops, but it still poses a problem.
Another issue that I thought of was that a client with a lower ID would always end up having their message sent first each loop. This isn't that big of a deal but if there was a situation, say, a trivia game, where two clients entered the correct answer in the same loop then the client with the lower ID would end up saying the answer "first" every time.
Thanks in advance.
If all I/O is being handled through a central server, a simple (but certainly not elegant) solution is to create a barrier around the I/O mechanisms to each client. In the simplest case this can just be a mutex. Associate that barrier with each client and anytime someone wants to send that client something (a complete message), lock the barrier. Unlock it when the complete message is handled. That way only one client can actually send something to another client at a time. In C++11, see std::mutex.
I am learning Winsock and trying to create some easy programs to get to know it. I managed to create server which can handle multiple connections also manage them and client according to all tutorials, it is working how it was supposed to but :
I tried to make loop where I check if any of clients has disconnected and if it has, I wanted to close it.
I managed to write something which would check if socket is disconnected but it does not connect 2 or more sockets at one time
Anyone can give me reply how to make working loop checking through every client if it has disconnected and close socket ? It is all to make something like max clients connected to server at one time. Thanks in advance.
while (true)
{
ConnectingSocket = accept (ListeningSocket, (SOCKADDR*)&addr, &addrlen);
if (ConnectingSocket!=INVALID_SOCKET)
{
Connections[ConnectionsCounter] = ConnectingSocket;
char *Name = new char[64];
ZeroMemory (Name,64);
sprintf (Name, "%i",ConnectionsCounter);
send (Connections[ConnectionsCounter],Name,64,0);
cout<<"New connection !\n";
ConnectionsCounter++;
char data;
if (ConnectionsCounter>0)
{
for (int i=0;i<ConnectionsCounter;i++)
{
if (recv(Connections[i],&data,1, MSG_PEEK))
{
closesocket(Connections[i]);
cout<<"Connection closed.\n";
ConnectionsCounter=ConnectionsCounter-1;
}
}
}
}
Sleep(50);
}
it seems that you want to manage multiple connections using a single thread. right?
Briefly socket communication has two mode, block and non-block. The default one is block mode. let's focus your code:
for (int i=0;i<ConnectionsCounter;i++)
{
if (recv(Connections[i],&data,1, MSG_PEEK))
{
closesocket(Connections[i]);
cout<<"Connection closed.\n";
ConnectionsCounter=ConnectionsCounter-1;
}
}
In the above code, you called the recv function. and it will block until peer has sent msg to you, or peer closed the link. So, if you have two connection now namely Connections[0] and Connections[1]. If you were recv Connections[0], at the same time, the Connections[1] has disconnected, you were not know it. because you were blocking at recv(Connections[0]). when the Connections[0] sent msg to you or it closed the socket, then loop continue, finally you checked it disconnect, even through it disconnected 10 minutes ago.
To solve it, I think you need a book Network Programming for Microsoft Windows . There are some method, such as one thread one socket pattern, asynchronous communication mode, non-block mode, and so on.
Forgot to point out the bug, pay attention here:
closesocket(Connectons[i]);
cout<<"Connection closed.\n";
ConnectionsCounter=ConnectionsCounter-1;
Let me give an example to illustrate it. now we have two Connections with index 0 and 1, and then ConnectionsCount should be 2, right? When the Connections[0] is disconnected, the ConnectionsCounter is changed from 2 to 1. and loop exit, a new client connected, you save the new client socket as Connections[ConnectionsCounter(=1)] = ConnectingSocket; oops, gotting an bug. because the disconnected socket's index is 0, and index 1 was used by another link. you are reusing the index 1.
why not try to use vector to save the socket.
hope it helps~
I writing a small program that can Send File from Client -> Server (Send) and Server -> Client(Request).
Well done this part but the problems comes when:
1. I found the File on Server, How can I execute a cin on the client side?
2. How can I force my messages between Server and Client to be synced? I mean I dont want the Server to move to next step or freeze on the receive.
For Example(No Threading applied in this porblem):-
Server: Waiting a Message from Client.
Client: Send the Message.
Client: Waiting a Message from Client.
Server: Send the Message.
.....etc.
In a rare times the messages arrive on order but 99.999% of the time they don't and the program on two sides freeze.
The problem with the inorder messages was a thread on the client side who kept reading the inc replies without allowing the actual functions to see them.
However, about point 1.
I am trying in this code:
1. No shared resources so i am trying to define everything inside this function (part of it where the problem happening)
2. I was trying to pass this function to a thread so the server can accept more clients.
3. send & receive nothing special about them just a normal send/recv calls.
3. Question: if SendMyMessage & ReceiveMyMessage is going to be used by different threads, should I pass the socket to them with the message?
void ExecuteRequest(void * x)
{
RequestInfo * req = (RequestInfo *) x;
// 1st Message Direction get or put
fstream myFile;
myFile.open(req->_fName);
char tmp;
string _MSG= "";
string cFile = "*";
if(req->_fDir.compare("put") == 0)
{
if(myFile.is_open())
{
SendMyMessage("*F*");
cFile = ReceiveMyMessage();
// I want here to ask the client what to do after he found the that file exist on the server,
// I want the client to to get a message "*F*", then a cin command appear to him
// then the client enter a char
// then a message sent back to the server
// then the server continue executing the code
//More code
}
Client side:
{
cout <<"Waiting Message" <<endl;
temps = ReceiveMessage();
if(temps.compare("*F*") == 0)
{
cout <<"File found on Server want to:\n(1)Replace it.\n(2)Append to it." <<endl;
cin>>temps;
SendMyMessage(temps);
}}
I am using visual studio 2013
Windowx 7
thread am using: _beginthread (I removed all threads)
Regards,
On linux, there is a system call "select" using which the server can wait on the open sockets. As soon as there is an activity, like client wrote something, the server wakes up on that sockets and processes the data.
You are on windows platform. So :
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=vs.85%29.aspx
Is it right method client send data using the same connection accepted by server?.
The situation is like this, I have blue tooth server running on my PC and on the other side I have android phone with client and server. From android side the client start connection. I am using blue-tooth chat example from android samples.
And the server-client on android look like
BluetoothSocket socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
And in the PC side I am using Bluez libraries to implement server and client.
The code includes blue tooth receive thread and a main thread, whenever the server accept a connection from android phone I just assign the socket value to a global variable and whenever the client need to send data it send using the same socket ,
Server:-
int GLOBAL_CLIENT;
void* recive_bluetooth_trd(void*)
{
...............................
..............................
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
GLOBAL_CLIENT=client;
while(1){
bytes_read = read(client, buf, sizeof(buf));
....................
...................
}
Client:-
void clinet(char *msg, int length){
........................
int bytes_write=write(GLOBAL_CLIENT,message, length);
..........................
}
My question is, Is it a right method ? The problem is that some times the client send data successfully from PC but not receiving on android side.
The biggest problem I see is that you won't ever leave your while(1) loop, even when the client disconnects. Read will return immediately forever with 0 bytes read (check for a return code of <= 0), trying to signal that the socket is disconnected. Your code will go into a tight infinite loop and use up all the CPU resources it can get its single-threaded hands on.
You need to make sure you ALWAYS check your socket and IO return codes and handle the errors correctly. The error handling for sockets is usually about 3x the actual socket code.
Unless of course the .......... stuff is the important bits. Always tough to tell when people hide code relevant to the question they are asking.
Seems correct to me, but after read you have to NUL ('\0') terminate your buffer if you are treating with strings:
buf[bytes_read] = '\0';