Two way socket communication - c

I'm trying to write a simple two way socket communication using C. So far, the main while loop for my client.c file looks like this:
while ( gets(str) != NULL ) {
sSize = send(s, str, strlen(str), 0);
if ( len != strlen(str) ) {
exit(1);
}
else {
rSize = recv(s, buffer, 64, 0);
buf[rSize] = '\0';
printf("%s\n", buffer);
}
}
while loop in sever.c looks like this:
while ( 1 ) {
gets(str);
send(p, str, strlen(str), 0);
rSize = recv(p, buffer, 32, 0);
if ( rSize < 0 ) {
exit(1);
}
buf[len] = '\0';
else{
printf("%s\n", buffer);
}
}
The program compiles normally and I can establish connection between both machines, but when I send message either from client or server, I get an anomaly:
Sending message 'hi' from client
client -------------------------- server
hi
If I go to server to send 'you' message, I get:
client -------------------------- server
hi
you
you hi
Not sure exactly how this is, but what I'm trying to achieve is that, whenever message is sent from either client or server, it should display immediately on the other side.

Please note that gets() is a blocking function. Initially both client and server are blocked in gets() waiting for input. When you type 'hi' on client, it sends this to the server which is still blocked on gets.
After sending hi, the client blocks on recv() call, waiting for message from server. On the other side, server hasn't still received the 'hi' message send by the client.
When you type 'you' on the server, it comes out of gets() and sends 'you' to client. After that the server calls recv() and reads the 'hi' sent by the client. Since the client is already waiting in recv(), it reads 'you' sent by the server.
Thus the program is working absolutely the way it has been implemented. Please mention your object, not sure what do you want to achieve.

Related

C - Why does my server socket stop receiving data delivered by send() after one request?

I'm creating a program in c which listens to GET and PUT requests and routes them to an httpserver. The problem is that after about N requests (N = number of servers), the httpserver stops responding because it doesn't receive the data from the client after the first request.
I forward the data by accepting client connections using accept(), read from the client socket and put the data from the client in a buffer using recv until it returns 0. I send this buffer to the server using send():
int connect(int from, int to) {
char buf[BUFFSIZE];
int n = recv(from, buf, BUFFSIZE-1, 0);
if (n == 0) {
return 0;
}
buf[n] = '\0';
n = send(to, buf, n, 0);
if (n == 0) {
return 0;
}
return n;
}
int acceptfd = accept(listenfd, &client_addr, &client_addrlen)
connect(acceptfd, serverfd)
I was wondering if I wasn't properly detecting the end of the client's input, but I print the output of send() returns exactly the number of bytes I expect, but server doesn't receive it.
The server works perfectly every time, when I make requests to it independently. The server receives connections similarly (I can't change the server), it accepts client connections using accept() and it reads from that socket using recv. To clarify, I do not have the server code, but I have my own that works similarly to the one that I am using for this project that I also tested with (the problem persists) :
char buff[BUFF_SIZE + 1];
int client_sockd = accept(server_sockd, &client_addr, &client_addrlen);
int bytes = recv(server_sockd, buff, BUFF_SIZE, 0);
Is there something I could be misunderstanding about send() or maybe buffers? I have tried using the O_NONBLOCK flag and I use select() to determine which socket to read from so I don't know if blocking is the issue.

Multiclient server socket doesn't print the client messages

I'm trying to implement a client-server application with multiclients using threads. Just to try, I would like to print the messages from each client, but when I send messages from a client, the server does not print anything.
Server (thread code)
void comunicationHandler(void *socket)
{
int sock = *(int*) socket;
char msg[2000];
while ((strcmp(msg, "!quit")) != 0) {
if (recv(sock, msg, 2000, 0) < 0)
puts("Error recv");
printf("%s", msg);
}
puts("Client Disconnected\n");
}
when I send "!quit", the Server goes in a infinite loop printing the messages
Client
for(;;) {
printf("\nInserisci il msg: ");
scanf("%s", msg);
if (strcmp(msg, "!quit") == 0)
break;
write(sd, msg, 2000);
}
There are multiple problems with your code:
TCP is stream based, there is no guarantee that all the bytes you send will be received in one shot on the other side. You need to modify code to check what is the number of bytes received and is it atleast equal to the size of "!quit" before you go in for the "strcmp" comparison.
Better to null terminate the buffer once you receive the buffer equal to the size of "!quit"
It is not clear as to why you are sending a 2000 bytes buffer from the client when you intend to send only "!quit". Modify and send only appropriate size as needed
Check recv return value against 0 also
Break out of the loop in both server and client once the Job is done.
Server goes in a infinite loop
You want to test recv()'s result against 0 and quit in this case. 0 indicates that the client orderly closed the connection.

Knowing when Client has finished reading from the socket in C

I am writing a client-server program in c where I have to send multiple image files from the server to the client. Is there any way for the server to know when the client has finished reading from socket, creating the image file locally, and successfully written to it? P.S. I already tried sending a message to the socket and when I try to read the socket from the server, the program hangs. Any help will be much appreciated.
Here is a function from the Server code which sends the file to socket:
while(1)
{
unsigned char buf[256] = {0};
int n = fread(buf,1,256,fp);
if(n>0) { send(sockfd,buf,n,0); }
if(n<256) {
if(feof(fp))
printf("Sent to socket\n");
break;
}
}
fclose(fp);
}
char buf[5]
read(sockfd,buf,5);
if(strcmp(buf,"ready")==0) //send more files
And here is a function from the client to write to the file:
FILE* fp;
fp = fopen(file_path,"ab");
char buf[256];
int num;
int total=0;
while(( num = recv(sockfd,buf,256,0))>0)
{
total+=num;
fwrite(buf,1,num,fp);
}
fclose(fp);
write(sockfd,"ready",5);
}
When I do a read on the server after one file transfer, the program hangs.
You problem is here in the client:
while(( num = recv(sockfd,buf,256,0))>0)
recv() will only return 0 at end-of-file - ie when the server shuts down the sending side of the socket. However your server isn't doing that - it's waiting for a response from the client. This means you deadlock.
If you want to send multiple images in the one connection, you need to send your client some information to allow it to tell when one image ends. One way to do this is to first send your client the size of the file it should expect, then the file data. The client can then keep track of how many bytes it's recieved, and send the "ready" reponse after that.
You need a kind of protocol to allow :
the server to tell the client that all has been written
the client to tell the server that all has been read
If you only send one file, the simplest way is to use shutdown(sockfd, SHUT_WR) server side after all data has beed sent. That way the client will get a 0 as return from recv signaling end of data and will be able to send its acknowledgement. But you can no longer write on the socket server side.
If you want to be able to send more than one file, you will have to imagine a cleverer protocol. A common one would be to send blocs of data preceded by their size
short sz = htons(n); /* deals with possible endianness problems */
send(sockfd, &sz, sizeof(short), 0)
send(sockfd, buf, n);
And a sz == 0 (with no buf ...) would signal end of data
This would still be a simple protocol with no error recovery, but at least it can work when no incident happens.

When does recv() return?

I have made a server and a client using sockets. My server is written in c and runs on my raspberry pi and my client is written in Swift and is running on my Mac/iPhone.
What i don't get is when my servers recv() function execute what i have sent from my client? If i send like 0-10 bytes it doesn't return from recv() function before i close the connection. But if I send 100+ bytes it executes immediately.
I would like my server to return from recv() every time i write a message from my client.
Here is my servers recv() function:
//Receive a message from client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
printf("%s", client_message);
}
Here is my Clients write method:
func SendMsg(msg:String) -> Int{
return outputStream!.write(msg, maxLength: countElements(msg))
}
Everything works fine beside I'm not in control of when my server executes my messages.
Output to stdout is by default line buffered, so when using printf, make sure there is a newline character ('\n') at the end. If the message itself doesn't already contain a newline, then :
printf("%s\n", client_message);
As a side note : also make sure that client_message is properly null terminated before passing it to printf, or you might run into undefined behavior (ref. #JoachimPileborg's comment). If you can't ensure null termination, this would do the trick too :
printf("%.*s\n", read_size, client_message);
The server doesn't get the message because the client hasn't sent it.
You need to fflush the outputStream on the client side!

Asynchronous transfer message between two clients

This time I code a chat server and client. The idea is this.
The server uses the select method for with a readfd(FD_SET) to seek which of the clients connected on it have something to send. If it founds something it send it to the rest of clients.
Here is the select function on server and a part of server's code.
SelectResults = select(maxDescriptor+1,&BackUpfdread,NULL,NULL,&time);
I use the select function in client too, to make it seek for incoming and outcoming messages.(these that server sends from other clients and these that this client want to send).
Well, the client in the select function has a fdread and fdwrite (FD_SET).
Here is the part of the code that client has for the connection and for the chat.
The problem is that if i connect two clients on the server message transfer isn't concurrent and that means that clients cannot chat correctly.
Finally i thought to use threads in server. One thread for waiting to receive and one for sending to the clients, but i want to hear and your opinion.
In the client you don't really need that loop from 0 to maxDescriptor. Just check if ConnectSocket is set. Something like this:
// Main loop starts here
for(; ;)
{
memset(SentBuff, 0, sizeof(SentBuff));
printf("Write: ");
gets_s(SentBuff, sizeof(SentBuff));
// Copy the fdread into BackUpfdread and fdwrite to BackUpfdwrite.
BackUpfdread = fdread;
BackUpfdwrite = fdwrite;
SelectResults = select(maxDescriptor+1,&BackUpfdread,&BackUpfdwrite,NULL,&timer);
if(SelectResults == -1)
{
perror("Client-select() error!\n");
exit(1);
}
if (FD_ISSET(ConnectSocket, &BackUpfdread))
{
RecvBytes = recv(ConnectSocket, RecvBuff, sizeof(RecvBuff), 0);
if(RecvBytes > 0)
{
printf("%s\n",RecvBuff);
// Cleaning the Receive Buffer
memset(RecvBuff,0,sizeof(RecvBuff));
}
}
if (FD_ISSET(ConnectSocket, &BackUpfdwrite))
{
SentBytes = send(ConnectSocket, SentBuff,sizeof(SentBuff),0);
// Cleaning the Sent Buffer
memset(SentBuff,0,sizeof(SentBuff));
}
} // Main loop ends here
Also don't forget to check for errors from send and recv. Especially recv is important, as it's the call that will tell you the server has disconnected.
Edit: Another important thing to note, is that the socket may be writeable always, so add a check if there is something to write before you check if the socket is writeable.

Resources