C++ client needs to find out socket was closed by twisted server - c++

I have a twisted server that does something and then closes the connection. The python clients understand with
clientConnectionLost(self, connector, reason)
that the connection was closed and that works fine.
However, I also have a C++ client communicating with the same twisted server. It currently doesn't seem to understand that the connection/socket was closed. How do I check for this?
string tcp_client::receive(int size=1024)
{
char buffer[size];
string reply;
int msg = recv(sock , buffer , sizeof(buffer) , 0);
// Receive a reply from the server
if(msg < 0)
{
puts("recv failed");
// Exit the programm
exit(0);
}
reply = buffer;
return reply;
}
is the C++ client's receive code.
How do I reach the same/similar functionality of clientConnectionLost with the C++ client?

From man recv:
The return value will be 0 when the peer has performed an orderly shutdown.
So after recv call, you can write:
string tcp_client::receive(int size=1024)
{
char buffer[size];
string reply;
// Receive a reply from the server
int msg = recv(sock , buffer , sizeof(buffer) , 0);
if(msg < 0)
{
puts("recv failed");
// Exit the programm
exit(0);
}
else if (0 == msg)
{
// the connexion has been closed by server
puts("Connexion lost!");
// close the socket
close(sock);
// return something
return string("");
}
reply = buffer;
return reply;
}

Related

How to handle 10093(WSANOTINITIALISED) error when invoke accept method

Recently my code meet some issue. My programme work as server and listen to ONE client to connect, then send some commands to my programme. Then I will handle this command and return the value to client side.
But now I got the issue accept() method will get 10093(WSANOTINITIALISED) error and seems accept() method didn't block there.
It is not always happened. I tested the programme. Sometimes it works very well. Client side connected to my programme and send first command. Then my programme handle the command and send back return value. Then stopped the connection(closesocket(sClient);). Then Client side connected to my programme again and send second command...While time to time it happened accept() get 10093(WSANOTINITIALISED) error and client side will fail to connect to my programme any more. and the while loop(while (true && !m_bExitThread)) also didn't block.
My questions are:
Why did it happen? did someone meet the same issue? I believe my code should be correct, otherwise why most of time it works well.
If this 10093 error comes, how should I handle it? Do I need to closesocket and wait for Client side connect again? or do I need to WSACleanup(); and try to start this socket Thread totally again?
Below is the code. it is a thread I start it when my programme start up and stop it when programme stopped.
UINT CMainFrame::RunSocketThread()
{
m_bExitThread = false;
WORD wSockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(wSockVersion, &wsaData) != 0) // Here always success, no problem
{
LOGL(ILoggingSink::LogLevel::Error, _T("WSAStartup error !"));
return 0;
}
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (slisten == INVALID_SOCKET)
{
LOGL(ILoggingSink::LogLevel::Error, _T("socket error !"));
return 0;
}
sockaddr_in stSocketAddr;
stSocketAddr.sin_family = AF_INET;
stSocketAddr.sin_port = htons(7700);
stSocketAddr.sin_addr.S_un.S_addr = INADDR_ANY;
if (bind(slisten, (LPSOCKADDR)&stSocketAddr, sizeof(stSocketAddr)) == SOCKET_ERROR)
{
LOGL(ILoggingSink::LogLevel::Error, _T("bind error !"));
return 0;
}
if (listen(slisten, 5) == SOCKET_ERROR)
{
LOGL(ILoggingSink::LogLevel::Error, _T("listen error !"));
return 0;
}
SOCKET sClient;
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
char revData[255];
while (true && !m_bExitThread)
{
// Waiting for connection
sClient = accept(slisten, (SOCKADDR*)&remoteAddr, &nAddrlen);
if (sClient == INVALID_SOCKET) // Here I can get error code 10093(WSANOTINITIALISED)
{
LOGL(ILoggingSink::LogLevel::Error, _T("accept error %d!"), WSAGetLastError());
continue;
}
// revice data
int ret = recv(sClient, revData, 255, 0);
if (ret > 0)
{
revData[ret] = 0x00;
ParseJsonCommand(revData);
}
// send data
// Here I wait for programme finished handling the income command and return a value, otherwise just sleep and wait
while (CmdLineInfo::m_eReturn == ReturnTypeEnum::kNull)
{
Sleep(100);
}
const char* sendData;
CString strData;
strData = "{\"Command\":\"";
strData += CmdLineInfo::s_sLFODCommandName;
strData += "\", \"ReturnValue\":\"";
if(CmdLineInfo::m_eReturn == ReturnTypeEnum::kSuccess)
strData +="1\"} ";
else
strData += "0\"} ";
CStringA strAData(strData);
sendData = strAData;
send(sClient, sendData, strlen(sendData), 0);
closesocket(sClient);
}
closesocket(slisten);
WSACleanup();
return 0;
}

recv does not return after udp socket closed in linux

I am trying to write client server application using udp protocol, but I have problem with connection ending.
I open two sockets (one is a "server" and the other is a "client"), and while the server receiving from the client with async, the client send him one simple message that printed to the console.
After some sleep (to be sure the server will call again to recv) the client and server socket getting closed.
At this point I expected the recv will return -1 and the async will end.
But what actualy happen is that the recv stuck forever*.
If just before closing the socket I sending an empty package (sendToMakeExit variable set to true in the code), the recv return with that empty package, and only after next call it return -1, although the socket was closed in the first calling.
const bool sendToMakeExit = false;
const int port = 2000;
const auto addr = "127.0.0.1";
int serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
sockaddr_in target;
target.sin_family = AF_INET;
target.sin_port = htons(port);
inet_pton(AF_INET, addr, &target.sin_addr);
bind(serverSocket, (sockaddr *) &target, sizeof(target));
auto readAsync = std::async(std::launch::async, [&serverSocket] {
const int MAX_READ = 4096;
char readBuf[MAX_READ];
ssize_t actualRead;
do {
actualRead = recv(serverSocket, readBuf, MAX_READ, 0);
if (actualRead > 0) {
cout << readBuf << endl;
}
} while (actualRead != -1);
});
int clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
connect(clientSocket, (sockaddr *) &target, sizeof(target));
this_thread::sleep_for(chrono::seconds(1));
send(clientSocket, "test", 5, 0);
this_thread::sleep_for(chrono::seconds(1));
close(clientSocket);
if (sendToMakeExit) {
sendto(serverSocket, nullptr, 0, 0, (sockaddr *) &target, sizeof(target));
}
close(serverSocket);
*If I run this code in debug and create new breakpoint when the recv is stuck surprisingly the recv return with -1.
How can I getting the recv will return -1 when I close the socket?
Closing a socket does not guarantee that any function call in another thread that is still using that socket immediately returns. If you have calls that wait for data to come in, like recv(), select(), poll(), you must send some data to the socket for these calls to return. You do that in your code, but you don't actually exit when a zero-length UDP packet is received: change the end of the while-loop to:
} while (actualRead > 0);
However, I would recommend having a flag variable that indicates whether the thread should continue running or not, like so:
volatile bool running = true;
auto readAsync = std::async(std::launch::async, [&serverSocket, &running] {
...
while (running) {
...recv()...
}
});
...
running = false;
sendto(serverSocket, ...);
readAsync.wait();
close(serverSocket);
Note that I added a line to wait for readAsync to finish before closing the socket, in order to prevent any accidents from happening: there is a small window where the socket is invalidated, but readAsync might still call recv() on it. If you have even more threads, it might also happen that you close the socket in this thread, another thread opens a new socket and gets the same filedescriptor number as the one you just closed, and then the readAsync thread would use the wrong socket.

First recv() cannot read message sent from server

I'm writing a simple TCP server and client where the server echoes back the message to the client. But I have a problem with the first read()/recv() call from the client side. Whenever a client connects to the server, it sends a welcome message, but I cannot display the welcome message on the client side. What i get in return from recv()/read() is 0, which indicates that the socket is closed or 0 bytes read. I know it isn't closed since the server echoes back messages but with a delay(example bellow). The read()/recv() works fine after I've written to the server from the client side. So my question is:
Why does the first read()/recv() call receive return a 0?
TLDR; My client does not read()/recv() the welcome message sent from server. What am I doing wrong?
Server and client interaction(Notice empty 'Welcome message'):
As you can see, the socket isn't closed so the only reason read()/recv() returns 0 is because 0 bytes read.
Client code:
(SETUP NOT INCLUDED)
printf("Connected. \n");
memset(buffer, 0, 1025);
/********* PROBLEM IS THIS READ()/RECV() **********/
n = recv(sockfd, buffer, strlen(buffer), NULL);
if(n == 0){ //
//error("Error reading\n");
printf("Error reading socket.");
}
printf("Welcome message: \n%s", buffer);
while(1){
printf("\nPlease enter message: \n");
memset(buffer, 0, 256);
fgets(buffer, 255, stdin);
printf("You sent: %s", buffer);
n = write(sockfd, buffer, strlen(buffer));
if(n <= 0)
{
error("Error writing socket. \n");
}
//om bye, break
memset(buffer, 0, 256);
//Läser här endast efter write
n = read(sockfd, buffer, 255);
if(n < 0)
{
error("Error reading from socket. \n");
}
printf("You received: %s", buffer);
}
//end while
close(sockfd);
return 0;
Relevant Server code:
while(TRUE)
{
/* Clear socket set */
FD_ZERO(&readfds);
/* Add master socket to set */
FD_SET(masterSocket, &readfds);
/* For now maxSd is highest */
maxSd = masterSocket;
/* Add child sockets to set, will be 0 first iteration */
for(int i = 0; i < maxClients ; i++)
{
sd = clientSockets[i]; // sd = socket descriptor
/* If valid socket descriptor */
if(sd > 0)
{
FD_SET(sd, &readfds);
}
/* Get highest fd number, needed for the select function (later) */
if(sd > maxSd)
{
maxSd = sd;
}
}//end for-loop
/* Wait for activity on any socket */
activity = select(maxSd +1, &readfds, NULL, NULL, NULL);
if((activity < 0) && (errno != EINTR))
{
printf("****** Error on select. ******\n"); //no need for exit.
}
/* If the bit for the file descriptor fd is set in the
file descriptor set pointed to by fdset */
/* If something happend in the master socket, its a new connection */
if(FD_ISSET(masterSocket, &readfds))
{
//står här och läser
if((newSocket = accept(masterSocket, (struct sockaddr*)&address, (socklen_t*)&addrlen)) < 0)
{
perror("****** Could not accept new socket. ******\n");
exit(EXIT_FAILURE);
}
/* Print info about connector */
printf("New connection, socket fd is %d, ip is: %s, port: %d\n", newSocket, inet_ntoa(address.sin_addr), ntohs(address.sin_port));
/**************** THIS IS THE WRITE THAT DOESN'T GET DISPLAYED ON CLIENT ******************/
if( send(newSocket, message, strlen(message), 0) != strlen(message))
{
perror("****** Could not sent welcome message to new socket. ******\n");
}
puts("Welcome message sen successfully");
/* Add new socket to array of clients */
for(int i = 0; i < maxClients; i++)
{
if(clientSockets[i] == 0)
{
clientSockets[i] = newSocket;
printf("Adding socket to list of client at index %d\n", i);
break;
}
}
}//end masterSocket if
/* Else something happend at client side */
for(int i = 0; i < maxClients; i++)
{
sd = clientSockets[i];
if(FD_ISSET(sd, &readfds))
{
/* Read socket, if it was closing, else read value */
//denna read kan vara fel
if((valread = read( sd, buffer, 1024)) == 0)
{
getpeername( sd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
printf("Host disconnected, ip %s, port %d.\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));
close(sd);
clientSockets[i] = 0;
}
else
{
buffer[valread] = '\0';
send(sd, buffer, strlen(buffer), 0);
}
}
}
I know this is a big wall of text but i am very thankful for anyone who takes their time with this problem.
The third arg to recv specifies a number bytes to read from the socket. And now look at your code:
memset(buffer, 0, 1025);
recv(sockfd, buffer, strlen(buffer), NULL);
First, you zero out whole buffer and then call strlen on it. No wonder it returns 0, as strlen counts non-zero bytes.
Instead, put the buffer length into a variable and use it everywhere:
const int bufSize = 1025;
memset(buffer, 0, bufSize);
recv(sockfd, buffer, bufSize, NULL);
I'm not sure if it's the sole cause of the issue but... in your client code you have...
memset(buffer, 0, 1025);
Then shortly after...
n = recv(sockfd, buffer, strlen(buffer), NULL);
strlen(buffer) at this point will return zero, so the call to recv does exactly what is requested -- it reads zero bytes.
Note also that the welcome message as sent by the server is not null terminated. Thus, your client has no way of knowing when the welcome message ends and the subsequent data begins.

ZeroMQ can't send twice and then receive twice with nothing in between

I'm trying to write a client/server application with ZeroMQ. I've written a server which sends two messages via zmq_send() one right after the other in response to a GET_DATA message from the client.
The client sends GET_DATA and then tries to call zmq_recv() twice to get both messages sent by the server. Unfortunately the second call to zmq_recv() fails in the client with a -1 return and no errno.
In response to GET_DATA the server simply calls:
zmq_send (responder, "**start**", 9, 0);
zmq_send (responder, "**done**", 8, 0);
Here is the code of the client:
#include "stdafx.h"
#include "zmq.h"
int _tmain(int argc, _TCHAR* argv[])
{
printf ("Connecting to server.\n");
void *context = zmq_ctx_new ();
void *requester = zmq_socket (context, ZMQ_REQ);
zmq_connect (requester, "tcp://localhost:5555");
char szCommand[] = "GET_DATA";
zmq_send(requester, szCommand, sizeof(szCommand), 0);
char buffer[512];
int nLen = zmq_recv(requester, buffer, sizeof(buffer) - 1, 0);
if( nLen >= 0 ) printf("%*.*s\n", nLen, nLen, buffer);
nLen = zmq_recv(requester, buffer, sizeof(buffer) - 1, 0);
if( nLen < 0 ) printf("errno = %s\n", strerror(errno));
printf("done\n");
zmq_close (requester);
zmq_ctx_destroy (context);
fgetc(stdin);
return 0;
}
The output of the client is:
Connecting to Server.
**start**
errno = No Error
done
Can someone please explain why the second call to zmq_recv() returns -1 in the client?
Note: in a previous version I was getting errno of 9 (which seems to be bad file or something).
EDIT for posterity: This was written on Win32 which should use zmq_errno() instead of accessing errno directly but I only learned that later, so this problem did cause some noise here.
Req-rep socket types in zeromq is following a state-machine, so you can request and than must receive, in your case you receive twice which is not supported. However you can use multipart messages, on the server side, on the first send call with ZMQ_SNDMORE in the flags parameter.
Like so:
zmq_send(response, "Part1", 5, ZMQ_SNDMORE);
zmq_send(response, "Part2", 5, 0);

Why for each write message from client this program make a new process in C/C++?

I am trying to design an echo server which has concurrently feature. It means, Server for each client, it create a parent and child processes. It is for a game server and each client play separately. I have come up with following code but I have no Idea why each time there is a message from client to server it starts to create a new process and start from for(;;){ // Run forever. As I said I think I must have one process for each client. I expect every process to remain in HandleTCPClient until client close its socket
Other issue is where can I initial my datas so each children process share it with itself.
#include "wrappers.h" // socket wrapper fns
#include <sys/wait.h> // for waitpid()
#define RCVBUFSIZE 32 // Size of receive buffer
void HandleTCPClient(int ClntSocket);
extern "C" void SigChldHandler( int Signum );
int i = 0;
int main(int argc, char *argv[])
{
int ServSock; // Socket descriptor for server
int ClntSock; // Socket descriptor for client
unsigned short EchoServPort; // Server port
sockaddr_in EchoServAddr; // Local address
sockaddr_in EchoClntAddr; // Client address
pid_t ProcessID; // Process ID from fork()
unsigned int ChildProcCount = 0; // Number of child processes
EchoServPort = SERV_TCP_PORT;; // First arg: local port
// Create socket for incoming connections
ServSock = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Construct local address structure
memset((char*)&EchoServAddr, 0, sizeof(EchoServAddr)); /* Zero out structure */
EchoServAddr.sin_family = AF_INET; /* Internet address family */
EchoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
EchoServAddr.sin_port = htons(EchoServPort); /* Local port */
// Bind to the local address
Bind(ServSock, (sockaddr*)&EchoServAddr, sizeof(EchoServAddr));
// Mark the socket so it will listen for incoming connections
Listen(ServSock, 5);
signal(SIGCHLD, SigChldHandler); // for preventing zombies
for(;;){ // Run forever
// Set the size of the in-out parameter
socklen_t ClntLen = sizeof(EchoClntAddr);
// Wait for a client to connect
ClntSock = Accept(ServSock, (sockaddr*) &EchoClntAddr,&ClntLen);
//Startin point of new new player to server
// ClntSock is connected to a client!
printf("Handling client %s\n", inet_ntoa(EchoClntAddr.sin_addr));
// Fork child process and report any errors
if ((ProcessID = fork()) < 0){
perror("fork() failed");
exit(1);
}
if (ProcessID == 0){ // If this is the child process
close(ServSock); // Child closes (deallocates) its parent socket descriptor
HandleTCPClient(ClntSock);
exit(1); // Child process terminates
}
printf("With child process: %d\n", (int)ProcessID);
close(ClntSock); // Parent closes (deallocates) its child socket descriptor
ChildProcCount++; // Increment number of outstanding child processes
}
// NOT REACHED
}
void HandleTCPClient(int ClntSocket){
i++;
cout<<"Start of handling"<<endl;
cout<<"i="<<i<<endl;
char EchoBuffer[RCVBUFSIZE]; // Buffer for echo string
int RecvMsgSize; // Size of received message
// Receive message from client
if((RecvMsgSize = recv(ClntSocket, EchoBuffer, RCVBUFSIZE, 0)) < 0){
perror("recv() failed"); exit(1);
cout<<"Error"<<endl;
}
// Send received string and receive again until end of transmission
while(RecvMsgSize > 0){ // zero indicates end of transmission
// Echo message back to client
if(send(ClntSocket, EchoBuffer, RecvMsgSize, 0) != RecvMsgSize){
cout<<"Error"<<endl;
perror("send() failed"); exit(1);
}
// See if there is more data to receive
if((RecvMsgSize = recv(ClntSocket, EchoBuffer, RCVBUFSIZE, 0)) < 0){
cout<<"Error"<<endl;
perror("recv() failed"); exit(1);
}
}
close(ClntSocket); /* Close client socket */
cout<<"End of handling"<<endl;
}
extern "C" void SigChldHandler( int Signum ){
// Catch SIGCHLD signals so child processes don't become zombies.
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0 );
return;
}
Output for three messages form client to server:
Handling client 127.0.0.1
With child process: 40830
Start of handling
i=1
Handling client 127.0.0.1
With child process: 40831
Start of handling
i=1
Handling client 127.0.0.1
With child process: 40832
Start of handling
i=1
Handling client 127.0.0.1
With child process: 40833
Start of handling
i=1
End of handling
End of handling
End of handling
End of handling
As you can see it creates three processes and when I close the program it will close socket for each process!!!
> Edit2 Client side is abstracted:
int main()
{
int Sockfd;
sockaddr_in ServAddr;
char ServHost[] = "localhost";
hostent *HostPtr;
int Port = SERV_TCP_PORT;
//int BuffSize = 0;
//Connection
// get the address of the host
HostPtr = Gethostbyname(ServHost);
if(HostPtr->h_addrtype != AF_INET){
perror("Unknown address type!");
exit(1);
}
memset((char *) &ServAddr, 0, sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = ((in_addr*)HostPtr->h_addr_list[0])->s_addr;
ServAddr.sin_port = htons(Port);
//Do some operation
while(!loop){
// open a TCP socket
Sockfd = Socket(AF_INET, SOCK_STREAM, 0);
// connect to the server
Connect(Sockfd, (sockaddr*)&ServAddr, sizeof(ServAddr));
//Prepare message to send server
// write a message to the server
write(Sockfd, data, sizeof(data));
int Len = read(Sockfd, data, 522);
//work on the message from server
}
close(Sockfd);
}
Your client is creating a new socket and connecting it before each write/read, not using the already connected one multiple times. The client should create a socket, connect it to the server and then perform as many write/reads as needed, without creating a new connection.
The server correctly treats each new connection as a new client, and forks to handle it.
Regarding sharing data between forked processes, you could use shared memory as described here.
The client calls socket and connect for every message it writes
while (...) {
socket(...);
connect(...); /* here the server forks a new child process */
write(...);
}
If you want to avoid that, you must move the connection before the loop
socket(...);
connect(...); /* here the server forks a new child process */
while (...) {
write(...);
}