hello, i have a very big problem... i'm working with sockets in C. i ask a question to the server which sends me many answers. the problem is that the client receive the first response and the the connection is closed. what can i do? i tried with setsockopt()... SO_KEEPALIVE or SO_LINGER but i haven't resolved the problem. Can you help me? thanks a lot
to be more clear here is the code. the socket is automatically close after a time or after the client receive the first response... i'm not sure.
char* demarre_client( client_args * c_args,char* message, /char SERVEUR_PORT*/int port){ int socket_client=socket(PF_INET,SOCK_STREAM,0); memset(&(c_args->adresse_serveur),0,sizeof(c_args->adresse_serveur)); c_args->adresse_serveur.sin_family=AF_INET; c_args->adresse_serveur.sin_addr.s_addr=inet_addr(SERVEUR_IP); //int port=APHash(SERVEUR_PORT,strlen(SERVEUR_PORT)); c_args->adresse_serveur.sin_port=htons(port); int err=0;
if ((err=connect(socket_client, (struct sockaddr *) &(c_args->adresse_serveur), sizeof(c_args->adresse_serveur)))<0)
{
printf("CONNECT error %d\n", errno);
exit(-1);
}
if (send(socket_client, message, strlen(message), 0)!=strlen(message))
{
printf("send error!!\n");
exit(-2);
}
char* raspFin=(char* )malloc(sizeof(char)*1024);
strcpy(raspFin,"");
int num=-1;
int nn=0;
char* rasp=(char* )malloc(sizeof(char)*1024);
memset (rasp, 0, 1024 * sizeof(char ));
/* here it reads the first response and after he get out of while */
while ((num=recv(socket_client, rasp,1024,MSG_WAITALL))>0)
{
printf("recu %s mun=%d\n" , rasp,num);
strcat(raspFin,rasp);
strcat(raspFin,"\n");
rasp=(char* )malloc(sizeof(char)*1024);
memset (rasp, 0, 1024 * sizeof(char ));
}
if (num<0)
{
printf("rasp error!!\n");
exit(-3);
}
The client code looks fine, as far as I can tell. It looks like the connection is simply closed by the server. Are you sure there are more messages sent and that this sending succeeds on the server side?
Side note, but probably not related to the problem: You don't need to allocate a new buffer for rasp
in every iteration of the loop, you can reuse the old buffer. As you do it now you will leak some memory there. Also the string read by recv
is not necessarily null-terminated - better explicitly copy num
characters out of that buffer. And raspFin
is just 1024 characters long, so if you receive in total more than that, this buffer will overflow.
Are you sure you don't get all responses on first call?
TCP/IP is stream protocol without flow control built-in so different messages, sent using separate send()
calls, can be received in one recv()
. Because you use printf()
, it prints the buffer until it sees null-terminator - maybe other responses beyond the terminator?
Try to use some flow control, like sending message length prefix or using some special characters (like STX/ETX, but make sure your message doesn't contain such characters). You'd need to implement some flow-control anyway if you plan to use this software.
For now try replacing your printf()
with
char *ptr;
for (ptr = buffer; ptr <= buffer + num; ptr += strlen(ptr)+1;)
printf("%s\n", ptr);
It will print all strings from your response buffer.
And you don't need malloc()
inside the loop - you leak memory.
BTW SO_KEEPALIVE
and SO_LINGER
have nothing to do with this problem.
My suggestion would be to fire up Wireshark network analyzer and see what's happening packet-wise. In filters set
tcp.srcport == <insert_server_port> || tcp.dstport == <insert_server_port>
You should see what data actually gets sent to and who closes the connection (sends FIN/RST packets).