2

I am trying to create two programs a client and server, where the client opens a socket connection and then writes data to the server who on accepting the connection spawns a new threads and then detaches it, to handle the rest of the read/writes. The problem is that when I make multiple writes then reads from the client the reads aren't getting the correct data, however on the server side it prints that it sent the correct data.

This is what my code looks like to generate new threads, and how I handle those threads.

while(1){
 listen(sockfd,5);
 // determine the size of a clientAddressInfo struct
 clilen = sizeof(clientAddressInfo);
 int *newsockfd = malloc(sizeof(int));
 // block until a client connects, when it does, create a client socket
 *newsockfd = accept(sockfd, (struct sockaddr *) &clientAddressInfo, &clilen);
 // if the connection blew up for some reason, complain and exit
 if (*newsockfd < 0){
 error("ERROR on accept");
 }
 connection_args *args = malloc(sizeof(connection_args));
 args->file_descrp = newsockfd;
 pthread_t tid;
 pthread_create(&tid,NULL, handle_connect, args);
}
void * handle_connect(void* args){
 connection_args* connect_arg = (connection_args*)args;
 pthread_detach(pthread_self());
 int n = -1; 
 char buffer[256];
 bzero(buffer,256);
 //while not close;
 while(1){
 // try to read from the client socket
 n = read(*connect_arg->file_descrp,buffer,255);
 printf("input: %s\n", buffer);
 // if the read from the client blew up, complain and exit
 if (n < 0){
 error("ERROR reading from socket");
 }
 int fd;
 if(strcmp("open",buffer) == 0){
 fd = open("file.txt",0);
 bzero(buffer,256); 
 sprintf(buffer,"%d",fd);
 }else if(strcmp("read",buffer) == 0){
 char *read_buffer = malloc(sizeof(char)*256);
 bzero(read_buffer,256);
 fd = read(get_filedescrp(),read_buffer,30);
 bzero(buffer,256);
 sprintf(buffer,"%s,%d",read_buffer,fd);
 }else if(strcmp("close",buffer) == 0){
 break;
 }
 printf("buffer_send: %s\n",buffer);
 // try to write to the client socket
 n = write(*connect_arg->file_descrp,buffer,sizeof(buffer));
 // if the write to the client below up, complain and exit
 if (n < 0){
 printf("here!!\n");
 error("ERROR writing to socket");
 }
 bzero(buffer,256);
 }
 printf("Left thread\n");
 return NULL;
}
asked Dec 7, 2016 at 0:58
3
  • 1
    just in general I recommend using Wireshark and Netcat to debug network code. Wireshark of course will let you see what you're sending, and you can use nc as a known-working server and client so you can isolate your server and client, reducing the number of variables you take on at a time. Commented Dec 7, 2016 at 1:16
  • 1
    DO NOT call listen() inside your accept() loop. Call it one time BEFORE then entering the loop. And there is no need to malloc() your socket descriptors. And you are not null-terminating your buffer before performing null-terminated operations with it, like printf() and strcmp(). You are also not taking into account that TCP is a streaming transport, there is no guarantee that read() will receive complete strings, it can (and likely will) receive partial data at times. You need to delimit your commands on the sending side and look for those delimiters on the reading side. Commented Dec 7, 2016 at 2:18
  • Calling read() twice on the client side then gets me the correct data. How would I account for the fact that TCP is a streaming transport, keep calling read() until I get a non-null response? Also regarding the null terminating character, if a string is sent with the null terminating character do I need manually re-add it after I read? Commented Dec 7, 2016 at 2:47

2 Answers 2

1

You cannot implement client server communication over TCP/IP without some sort of protocol. The data written by the sender can be sliced and diced along the way and come in different chunk lengths to the reader side. You must have a way to tell if you have received a full frame before trying to interpret the data.

For example, you can use a very simple line based protocol: read data upto and including the '\n' byte. Reading one byte at a time into a lien buffer is somewhat inefficient but easy to implement.

answered Dec 7, 2016 at 10:56
Sign up to request clarification or add additional context in comments.

Comments

1

A socket read call may or may not return the entire data sent by client in a single call. Each read call returns number of bytes are that are read in that call. So the application should call read in a loop till expected number of bytes are read.

answered Dec 7, 2016 at 10:13

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.