Error in sending message from server to client - c

I writing a server program for computing engine in socket programming that displays the average of the numbers given by the client.
My code for client:
main()
{
//socket
//connect
gets(msg);
f=sscanf(msg,"%f",&num);
write(sockfd,msg,strlen(msg));
while ((n1=read(sockfd,result,Z))>0) {
write(1,result,n1);
}
}
In server:
while((rfd=read(sockfd,buff,Z))>0) {
sscanf(buff,"%f",&num);
sum=sum+num;
}
sum=sum/n;
snprintf(res,Z,"%f",sum);
write(sockfd,res,strlen(res));
The program doesnt work. If I remove the write in server then it is working.
If I just send a sample msg from server to client removing all computation then it works.
Could anyone tell me what is the error

Protocol error. The client is writing one number but the server is reading an infinite number of numbers. You need to either (a) change the server to read once, (b) send ahead the number of numbers to read or else (c) shutdown the client socket for output after writing the number and before reading the response.
You have a similar protocol error in the other direction. The server is writing one response but the client is looping forever. The server must close the socket after writing the reply.
You need to add `buff[rfd] = 0' after the read() in the server, otherwise sscanf doesn't know where to stop.

Related

How to know end of tcp session?

everyone, i want to know when my tcp connection will be finished.
I mean the next: my prog is a client and it sends any messages to server, but it doesn't know when the server will close connection (send FIN flag).
Its look like handshake, prog send first msg, then receive and send next msg on the same socket, then serv send FIN - flag, thats mean end of tcp session or end of handshake as you like.
My target is to know when server say FIN, im using stream socket.
I tryed to use var flags from msdn doc int recv(SOCKET s ... int flags);. But now i think it isnt what im looking for...
int partresult = recv(*my_sock, RcvBytes, Size, 0);
(I'm assuming you're referring to TCP as the FIN is used only in that context).
A call to recv() will tell you what you're looking for: it will return 0 when a FIN was received (i.e. the remote socket output was shutdown) (already stated by #RemyLebeau, and -1 in case of error).
I'm using this answer as an opportunity to warn you about not comparing its return value with the number of bytes expected to read, as TCP does not guarantee a single send() can be read with a single read(). So do not test if (partresult < RcvBytes) ....

C Socket Programming with Polling: How to detect if client hangs up

I am working on a simple C program where there are two source files: server.c and client.c
I connected everything properly with sockets, and I use the poll() function to poll the keyboard for data (as well as a shell connected to a pipe).
I am able to detect when the client uses the ^D and ^C command to know to kill the child process, and exit both client and server terminals.
However, is there a way to detect if the client hangs up (i.e. I explicitly click x on the client terminal tab)? Because right now, the server tab doesn't detect this, and doesn't close. I want to avoid using a timeout
You can continuously probe the client socket with the recv() sys call. It is designed to return 0 when the client disconnects.
while (1) {
//Get request from client, leave if client quits
if (recv(client_socket, client_request, sizeof(client_request), 0) == 0) {
break;
}
}
OR
// This while condition will fail when recv returns 0, because C
while (recv(client_socket, client_request, sizeof(client_request), 0)) {
// insert code here
}
Hope this helps 🤓

how to kill a tcp connection in a tcp server program if no FIN/ACK or RST received

I wrote a tcp server program(linux c) and run it on host B
if host A establishes a TCP connection with host B
then A shutdown without sending FIN/ACK
how do I write source codes inside tcp server to kill this tcp connection?
use raw socket to craft s fake RST?
or other ways?
thanks!
Just close() the server's end of the socket once it has determined that the connection is no longer available. Eventually, the socket will time out internally and start reporting errors to read/write operations, at which time you can then close it. If you do not want to wait that long then implement a timeout in your own code, either as a keepalive/ping command in your protocol, or just as a simple timer that keeps track of the last time the client exchanged any data with the server. If the timeout period expires, close the socket regardless of its actual state.
I'm not sure in this case, but if you create a binary file with all the open connections:
FILE *ptr_myfile;
ptr_myfile=fopen("test.bin","wb"); //opened sockets
//.. your code ..
sockfd[k] = socket(AF_INET, SOCK_STREAM, 0);
fwrite(&sockfd[k], sizeof(sockfd[k]), 1, ptr_myfile_soc);
//.. your code ..
close(ptr_myfile);
and if host A shuts down without sending FIN/ACK, in another executable you will read from that file and close the related sockets:
fread(&sockfd[k],sizeof(sockfd[k]),1,ptr_myfile_soc);
printf("closing %d \n",k );
close(sockfd[k]);

Server program is stuck at send

I am building a server client model in C. The clients connects to the server and they start exchanging data. However, the user can end the client at any time in the program, but the server is not notified about it. The server keeps sending that data even after the client is closed.
I was in the impression that send function will return -1 if the server is unable to send the data, but my server program just stuck at send
if((byteSent = send(new_fd, fileContents, strlen(fileContents), 0)) == -1){ //
the program just halts at the above line.
How do I overcome this problem?
//Code
exitT = 0;
//execution_count = 1;
for(i=0;i<execution_count;i++)
{
sleep(time_delay);
//getting the current time on the server machine
time_t t;
time(&t);
char *time=ctime(&t);
printf("The Execution time at server = %s\n",time);
system(exec_command);
/*Open the file, get file size, read the contents and close the file*/
// Open the file
fp = fopen(fileName,"r");
// Get File Size
fseek(fp,0,SEEK_END);
dataLength = ftell(fp);
rewind(fp);
fileContents = (char*)malloc(dataLength+1);
// Read File
fread(fileContents,1,dataLength,fp);
fileContents[dataLength] = '\0';
// Close file
fclose(fp);
printf("sockfd = %d \n",new_fd);
// send file length to client
rc=send(new_fd, &dataLength, sizeof(dataLength), 0) ;
printf("length of client data = %d \n",rc);
printf("sockfd = %d \n",new_fd);
// send time to client
rc=send(new_fd, time, strlen(time), 0) ;
printf("length of client time = %d \n",rc);
usleep(20000);
// Send file contents to Client
while(dataLength>0){
printf("sockfd = %d \n",new_fd);
if((byteSent = send(new_fd, fileContents, strlen(fileContents), 0)) == -1){
printf("bytes sent = %d \n",byteSent);
exitT = 1;
break;
}
dataLength-=byteSent;
}
//Delete the log file
sprintf(deleteCommand,"rm %s",fileName);
system(deleteCommand);
if(exitT == 1)
break;
}
bzero(fileName,sizeof(fileName));
bzero(exec_command,sizeof(exec_command));
bzero(deleteCommand,sizeof(deleteCommand));
//decClientNum();
kill(parent_id,SIGALRM);
close(new_fd); // parent doesn't need this
printf("STATUS = CLOSED\n");
exit(0);
}
Thanks
I assume you are coding for a Linux or Posix system.
When a syscall like send fails it returns -1 and sets the errno; you very probably should use errno to find out why it failed.
You could use strace to find out which syscalls are done by your sever, or some other one. Of course, use also the gdb debugger.
You very probably need to multiplex inputs or outputs. The system calls doing that are poll, select (and related ppoll and pselect). Read e.g. the select_tut(2) man page.
You may want to use (or at least to study the source code of) existing event oriented libraries like libevent, libev etc.. (Both Gtk and Qt frameworks provide also their own, which might be used even outside of GUI applications).
I strongly suggest reading about advanced unix programming and unix network programing (and perhaps also about advanced linux programming).
maybe you're using a tcp protocol and the server is waiting for an ACK. Try using udp if you want your connection to be asynchronous.
From the man page: No indication of failure to deliver is implicit in a send(). Locally detected errors are indicated by a return value of -1.
Proably something like this might help: http://stefan.buettcher.org/cs/conn_closed.html
I think I am pretty late in the party, but I think this answer might help someone.
If space is not available at the sending socket to hold the message to be transmitted, and the socket file descriptor does not have O_NONBLOCK set, send() shall block until space is available.
When send() function gets stuck, there might be a situation like, TCP window size has become 0. It happens when the other end of the connection is not consuming received data.
There might be a scenario like this, the receiving end process is running by GDB and segfault occurred.
The TCP connection remains established.
Data is being send continuously.
The receiver end is not consuming it.
Consequently the receiver TCP window size will keep decreasing and you can send data till it is greater than zero. Once it becomes 0, send() function will get stuck forever.
As the situation mentioned in the question is not a scenario of closed connection. When a process writes something on a closed TCP connection, it receives a signal SIGPIPE. Default handler of SIGPIPE terminates the process. So, in a closed connection scenario if you are not using your own SIGPIPE handler then process should be terminated by default handler whenever something is written on the socket.

C file transfer question

I implemented a client-server program that allows to transfer files b/w them. The server is using select() to check changes of sockets.
Every test is good except this one:
- When server is sending a huge file to client (not yet finished), client hit "Ctrl-C" to kill the client program, then the server is killed too :(
The snippet:
fprintf(stderr,"Reading done, sending ...\n");
if(send(sockClient, sendBuf, chunk_length, 0) < 0)
{
printf("Failed to send through socket %d \n", sockClient);
return -1;
}
fprintf(stderr,"Sending done\n");
When the client is killed, the server terminal displays:
user$./server
Reading done, sending ...
Sending done
Reading done, sending ...
Sending done
Reading done, sending ...
Sending done
Reading done, sending ...
user$
What's wrong with it?
Thanks for your answers!
You probably want to ignore SIGPIPE. Try adding something like this in your server startup:
#include <signal.h>
signal(SIGPIPE, SIG_IGN);
The send() call may be used only when the socket is in a connected state (so that the intended recipient is known). the return is the bytescount sent...
if(send(sockClient, sendBuf, chunk_length, 0) < 0)
so when disconnected, it skipped out...
MSG_NOSIGNAL is not portable and will not be available on Windows.

Resources