unexpected multithreaded server reaction - C - c

I'm working on a multithreaded server/client. The problem I have is that the server handling sometimes looks a little bit various. The message, which is send back is always correct, but the message the server prints out is a little bit weird. If it is a short word like "hello" everything works. If it is a long word or there are spaces in the string like "Binominalkoeffizient" the out-printed serversided message is:
Binomina
lkoeffiz
ient
fiz
Any idea where my mistake is?
PS: The server reaction is the same when I use telnet!
Server-Main:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include "server.h"
int main(int argc, const char * argv[]) {
int sock;
struct sockaddr_in server;
sock = socket(AF_INET, SOCK_STREAM, 0);
socketStatusCheck(sock);
puts("[*] Starting Server ...");
puts("[*] Initialize Server ...");
initializeServer(&server, 8888);
bindServerToAddress(sock, server);
puts("[*] Waiting for incomming connections ... ");
puts("");
listen(sock, 3);
connectionSwitch(sock);
close(sock);
return 0;
}
Server-File
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include "server.h"
void socketStatusCheck(int sock) {
if (sock == -1) {
perror("Error creating the socket: ");
exit(0);
}
}
void initializeServer(struct sockaddr_in *server, int port) {
server->sin_family = AF_INET;
server->sin_addr.s_addr = INADDR_ANY;
server->sin_port = htons(port);
}
void bindServerToAddress(int sock, struct sockaddr_in server) {
if (bind(sock, (struct sockaddr*) &server, sizeof(server)) < 0) {
perror("Error binding port: ");
}
}
void connectionSwitch(int sock) {
int nsock, lenbuf;
struct sockaddr_in client;
pthread_t pid = NULL;
lenbuf = sizeof(struct sockaddr_in);
while ((nsock = accept(sock, (struct sockaddr*) &client, (socklen_t*) &lenbuf))) {
puts("Client connected!");
if (pthread_create(&pid, NULL, connectionHandler, (void*) &nsock))
perror("Error creating thread: ");
}
if (nsock < 0) {
perror("Error accepting incomming client: ");
}
pthread_exit(pid);
}
void *connectionHandler(void *sockptr) {
int sock = *(int*) sockptr;
long isConnected;
char *smessage, *recvmessage;
smessage = "Hello! I am the server you just connected! \n";
write(sock, smessage, strlen(smessage));
recvmessage = malloc(5000 * sizeof(char)); // while ((isConnected = recv(sock, recvmessage, sizeof(recvmessage), 0)) > 0)
while ((isConnected = recv(sock, recvmessage, sizeof(recvmessage), 0)) > 0) {
//write(sock, recvmessage, sizeof(recvmessage));
send(sock, recvmessage, sizeof(recvmessage), 0);
puts(recvmessage);
}
if (isConnected == 0) {
perror("Client disconnected: ");
fflush(stdout);
}
free(recvmessage); recvmessage = NULL;
return 0;
}

This really has nothing to do with multithreading, and everything to do with the nature of SOCK_STREAM sockets.
Stream sockets are, as the name suggests, a stream of bytes; they do not preserve message boundaries such that what is sent with one call to send is received with one call to recv. A single send may be broken up across multiple recv calls, or multiple send calls may be coalesced into a single recv, or both. They do guarantee order, in that the bytes will be received in the same order they are sent.
You'll need to implement your own record marking, perhaps by inserting \0 characters to delimit words, or by using length prefixes.

This is normal behavior. When you use send you don't know how many bytes will be sent. It may happen that all the words , characters are sent.However there are ways to solve this problem. One way is to write a simple header to the string you send , which contains the length of the string you are sending . So you know when the string is ending . For example you can use a thread to look continuously for messages and because the header contains the length of the string you know when to print a \n.The behavior of the send cannot be altered , because it is the Kernel , that is doing this .

In addition to what the other answers say already:
Your code specifically asks to read 8 bytes at a time. recvmessage is a pointer, and pointers are 8 bytes on your system, so sizeof(recvmessage) is 8.

Related

Chat Program in C

First off, this is homework, so please no outright answers. I am writing a back and forth chat program in C. I'm extremely new to C (just started learning for this class). Currently I have three files:
server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include "chat.h"
#define SERVER_PORT 1725
#define MAX_PENDING 5
#define MAX_LINE 256
int main()
{
struct sockaddr_in sin;
char buf[MAX_LINE];
int len;
int s, new_s;
struct chat_packet packet;
/* build address data structure */
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
/* setup passive open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("simplex-talk: socket");
exit(1);
}
if ((bind(s, (struct sockaddr *)&sin, sizeof(sin))) < 0)
{
perror("simplex-talk: bind");
exit(1);
}
listen(s, MAX_PENDING);
/* wait for connection, then receive and print text */
while(1)
{
if ((new_s = accept(s, (struct sockaddr *)&sin, &len)) < 0)
{
perror("simplex-talk: accept");
exit(1);
}
/* Stay in the following loop until CTRL+C */
while (len = recv(new_s, &packet, sizeof(packet), 0))
{
fputs(packet.sender_name, stdout);
fputs(": ", stdout);
fputs(packet.data, stdout);
fputs("\nYou: ", stdout);
while (fgets(buf, sizeof(buf), stdin))
{
if(strlen(buf) > 144)
{
printf("Your message is too long. Please enter a new message.\n");
continue;
}
else
{
buf[MAX_LINE-1] = '\0';
strncpy(packet.data,buf,144);
char sender[8] = "Mason"; /*should be argv[index of name]*/
strncpy(packet.sender_name, sender, 8);
send(new_s, &packet, sizeof(packet),0);
}
}
}
close(new_s);
}
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "chat.h"
#define SERVER_PORT 1725
#define MAX_LINE 256
int main(int argc, char * argv[])
{
FILE *fp;
struct hostent *hp;
struct sockaddr_in sin;
char *host;
char buf[MAX_LINE];
int s;
int len;
struct chat_packet packet;
if (argc==2)
{
host = argv[1];
}
else
{
fprintf(stderr, "usage: simplex-talk host\n");
exit(1);
}
/* translate host name into peer's IP address */
hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
exit(1);
}
/* build address data structure */
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
/* active open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("simplex-talk: socket");
exit(1);
}
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
perror("simplex-talk: connect");
close(s);
exit(1);
}
/* main loop: get and send lines of text */
while (fgets(buf, sizeof(buf), stdin))
{
if(strlen(buf) > 144)
{
printf("Your message is too long. Please enter a new message.\n");
continue; /*This allows the user to re-enter a message post-error*/
}
else
{
buf[MAX_LINE-1] = '\0';
strncpy(packet.data, buf, 144);
char sender[8] = "Abby"; /*should be argv[index of name]*/
strncpy(packet.sender_name, sender, 8);
send(s, &packet, sizeof(packet), 0);
recv(s, &packet, sizeof(packet),0);
fputs(packet.sender_name, stdout);
fputs(": ", stdout);
fputs(packet.data, stdout);
fputs("\nYou: ", stdout);
}
}
}
chat.h
#include <stdint.h> /* Needed for unsigned types */
#define MAX_DATA_LEN 144 /* So we are on 16-bit boundary */
#define USER_NAME_LEN 8
/* You must send this packet across the socket. Notice there are
* no pointers inside this packet. Why?*/
struct chat_packet {
u_short version; /* 16 bits -- Set to version 2 in code */
char sender_name[8]; /* 64 bits */
char data[MAX_DATA_LEN]; /* Message goes in here */
};
Everything except what is in the client and server while loops were given to me by my instructor. The base part of the assignment is getting back-and-forth chat functionality. I'm running everything in PuTTY using the command line. I duplicate the session and run client in one and server in the other. To run:
./client serverName
./server
I am able to go back and forth one time, and then nothing else sends or receives. I am still able to type, but the two sessions cannot see each other's messages past the first back and forth. I am not sure where my code is wrong. Any advice would be appreciated, as I'm very new to the language. Thanks in advance!
Okay, here's my hint: Think about what happens when you recv() zero characters. Also, check what happens when the server calls accept() vs. when the client calls connect().
You might also want to check the return values of your recv() calls more judiciously. (and send(), for that matter; if a call can fail, check its return value!) Here's a hint from the man recv page:
RETURN VALUES
These calls return the number of bytes received, or -1 if an error occurred.
Also, if you aren't familiar with a debugger (such as gdb), I would recommend learning it. In a pinch, you might consider adding printf() statements to your code, to figure out what is happening.
Also, think about where your "blocking calls" are. If you're not familiar with what it means to be a "blocking call", we call it "blocking" when you call a function, and that function doesn't return ("blocks") until some specified thing happens. For example, your accept() will block until a connection is accepted. Your fgets() will block until a line of text is received. send() would block if you've already sent too much data, and the buffer is full. recv() would block until you've received the specified number of bytes. recv() also has a behavior you might not expect, that you may need to account for:
If no messages are available at the socket, the receive call waits for a
message to arrive, unless the socket is nonblocking (see fcntl(2)) in
which case the value -1 is returned and the external variable errno set
to EAGAIN. The receive calls normally return any data available, up to
the requested amount, rather than waiting for receipt of the full amount
requested; this behavior is affected by the socket-level options
SO_RCVLOWAT and SO_RCVTIMEO described in getsockopt(2).
In your case, your packets might be small enough that you won't run into cases where you have to reassemble them yourself. But it couldn't hurt to check.
I think that gives you some avenues to explore...

Socket Client/Server Chat (Threads Problems)

I have a problem with the implementation of a client/server chat.
The problem is that I can not handle the connection with two (or more) clients at the same time. In fact the server responds only to one client and not to all.
The server code is more less like this:
/*include*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <memory.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netdb.h>
/*define*/
#define PORT 5050
#define MSG_SIZE 100
#define NUM_UTENTI 5
//the thread function
void *fun_receiver(void *);
void *sender2(void *);
/*////////////////////// MAIN FUNCTION /////////////////////////////*/
int main(){
int serverfd , clientfd, c, *new_client;
struct sockaddr_in server_addr , client_addr;
//Create socket
serverfd = socket(AF_INET , SOCK_STREAM , 0);
//Prepare the sockaddr_in structure
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons( PORT );
//Bind
bind(serverfd,(struct sockaddr *)&server_addr , sizeof(server_addr));
puts("bind done");
//Listen
listen(serverfd , 5);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
//thread_id
int t=0;
pthread_t thread_receiver;
pthread_t thread_invio;
while(true){
clientfd = accept(serverfd, (struct sockaddr *)&client_addr, (socklen_t*)&c);
if (clientfd < 0){
perror("accept failed");
return 1;}
new_client=malloc(sizeof(int));
*new_client=clientfd;
if( pthread_create( &thread_receiver , NULL , fun_receiver , (void*) new_client) < 0){
perror("could not create thread");
return 1;
}
if( pthread_create( &thread_invio , NULL , sender2 , (void*) new_client) < 0){
perror("could not create thread");
return 1;
}
}//end while
close(serverfd);
return 0;
} //fine main
//////sender
void *sender2(void *clientfd)
{
int sock = *(int*)clientfd;
char buf[30];
while(true){
bzero(&buf, 30 * sizeof(char));
printf("Inserisci Messaggio3: ");
gets(buf);
int len, byte_sent;
len=strlen(buf);
byte_sent = send(sock, buf, len, 0);
}
return 0;
}
////receiver
void *fun_receivervoid *serverfd)
{
int sock = *(int*)serverfd;
char msg[MSG_SIZE];
bzero(&msg, MSG_SIZE * sizeof(char));
int read_size;
int count = 0;
while( (read_size=recv(sock, msg, MSG_SIZE * sizeof(char), 0)) > 0 ){
/*if(strcmp(msg, exit)==0){
printf("Arrivederci!\n");
close(sock);
}*/
printf("%s\n", msg);
bzero(&msg, MSG_SIZE * sizeof(char));
}
return 0;
}
the same code is in the client side after the connect(): there are two threads one for sending messages (to the server) and one for receiving messages (from the server). Both threads relies on the same client socket.
What happens:
The client1 connects to the server (writes and receives messages to/from the server) / / all ok!
The client2 connects to the server (writes messages to the server but doesn't receive anything..)
The problem is that if the server writes a message only client1 receives while client2 doesn't.
How is this possible? where I am wrong? I would like that server could send messages to all the clients not only one!
Your code can be improved in many ways. But I feel currently the critical problem here is in the
*new_client=clientfd;
The pointer (new_client) is not even initialized. And more over you want to use the value stored, in multiple threads.
In that case you need to have different memory areas, so that individual threads get the correct value of connection descriptor.
I would suggest to write
new_client = malloc(sizeof(int));
*new_client=clientfd;
Now individual threads will get the correct connection descriptor. I hope this will solve the problem.

Chat client in c

Problem:
I need some help with an error in my code. The chat client works when I only have one client running but if i use more clients. Only the last client messages will show up on my server. my client.c seems to work since it is sending but for some reason recv() is not getting the previous client send().
How code works:
I set up my server and spawn a new thread whenever a new client connects. the thread will handle the messages i get form the client and print it on the server screen.
Code:
CLIENT.C
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
#include <signal.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main(int argc, char ** argv){
//get port
//int port = atoi(argv[1]);
int server_port = atoi(argv[1]);
char * name =argv[2];
int namelength = strlen(name);
//set up server adress and socket
int sock = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(server_port);
//connect
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("connect failed");
exit(1);
}
//set up client name
char * buff = malloc(5000*sizeof(char));
//get the chatting
//char * other_message = malloc(5000*sizeof(char));
while(1){
printf("ENTER MESSAGE:\n");
char message[5000];
strcpy(message, name);
strcat(message,": ");
printf("%s", message);
scanf("%[^\n]",buff);
getchar();
strcat(message,buff);
int sent = send(sock , message , strlen(message) , MSG_DONTWAIT );
if (sent == -1)
perror("Send error: ");
else
printf("Sent bytes: %d\n", sent);
}
return 0;
}
SERVER.C
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <netdb.h>
#include <unistd.h>
#include <signal.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
pthread_t * threads = NULL;
int * client_fd = NULL;
int num_clients;
int thread_num;
void * client_handler(void * cl)
{
int * client = (int *)cl;
char * message = malloc(5000*sizeof(char));
printf("Connected: %d\n",*client);
int byte=1;
//recieve the message from clients
while(1)
{
byte=recv(*client, message , 5000 , 0);
if(byte< 0)
break;
//send message to all other clients
printf("%s\n",message);
printf("Recieved bytes:%d\n",byte);
memset(message, 0, 5000);
/*for(i=0;i<num_clients;i++)
if(client_fd[i]!=*client)
send(*client , message , strlen(message),0);*/
}
printf("finished: %d\n",*client);
return NULL;
}
int main(int argc, char ** argv)
{
//get the port
int port = atoi(argv[1]);
//set up socket
int socket_fd = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in server,client;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
//bind
if(bind(socket_fd, (struct sockaddr*)&server,sizeof(server)) < 0 ){
perror("binding error\n");
exit(1);
}
//listen
if( listen(socket_fd, 10) <0){
perror("binding error\n");
exit(1);
}
//accept incoming connectionns
threads = malloc(10*sizeof(pthread_t));
client_fd = malloc(10*sizeof(int));
int i=0;
int c = sizeof(struct sockaddr_in);
while(1)
{
int c_fd = accept(socket_fd,(struct sockaddr *)&client, (socklen_t*)&c);
if(c_fd < 0)
printf("error");
client_fd[i]=c_fd;
pthread_create(&threads[i],NULL,client_handler,(void *)(&c_fd));
i++;
num_clients=i;
}
return 0;
}
Sending C-style strings with strlen(). Does not send the terminating null. Use strlen()+1
Ignoring the value returned by recv(). TCP is a streaming protocol that only transfers bytes/octets. It does not transfer anything more complex. recv() may return one byte of your chat line, all of your chat line, or anything in between. To transfer any message more complex than one byte, you need a protocol and you must handle it. Yours is 'chat lines are null-terminated strings', so you need to call recv() in a loop and, using the returned value, concatenate the bytes received until the null arrives.
Trying to printf non-strings with "%s". You must not attempt to print out the received data until you are sure that a null has been received.

TCP client/server printing extra strings

I am trying to make a program with a server and multiple clients can connect to that server through the predefined port nummber. By the way, this is TCP in C. I have the following server code below:
SERVER CODE:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
void *connection_handler(void *);
int main(int argc , char *argv[])
{
int listenfd , connfd , c , *new_sock;
struct sockaddr_in servaddr , cliaddr;
listenfd = socket(PF_INET , SOCK_STREAM , 0);
if (listenfd == -1)
puts("SOCKET CREATION ERROR!");
puts("Socket created");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(54321);
bind(listenfd, (struct sockaddr*) &servaddr, sizeof(servaddr) );
listen(listenfd,2);;
c = sizeof(struct sockaddr_in);
while( (connfd = accept(listenfd, (struct sockaddr *)&cliaddr, (socklen_t*)&c)) ){
puts("Connection accepted");
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = connfd;
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("Thread Error Connection");
return 1;
}
puts("Handler assigned");
}
if (connfd < 0)
{
perror("accept failed");
return 1;
}
return 0;
}
void *connection_handler(void *socket_desc)
{
int sock = *(int*)socket_desc;
int read_size;
char client_message[51]="";
while( (read_size = recv(sock , client_message , 50, 0)) > 0 )
{
printf("%s",client_message);
}
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
free(socket_desc);
return 0;
}
CLIENT CODE:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
socklen_t len = sizeof(servaddr);
char mesg[1024];
if(argc!=2){
printf("Usage: %s <ip_addr>\n",argv[0]);
exit(1);
}
sockfd = socket(PF_INET,SOCK_STREAM,0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(54321);
inet_pton(AF_INET,argv[1],&servaddr.sin_addr);
connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
while(1){
fgets(mesg,sizeof(mesg),stdin);
sendto(sockfd,mesg,strlen(mesg),0,(const struct sockaddr *)&servaddr,len);
}
close(sockfd);
return 0;
}
I get the following output:
Socket created
Connection accepted
Handler assigned
Hello There!
What could be the problem?
I don't know?
the problem?
Hey!
't know?
the problem?
I typed in the following strings in the client terminal:
Hello There!
What could be the problem?
I don't know?
Hey!
The problem is when I typed the third string, the output is the third string with some parts of the second string still appearing. What could be the problem? Thanks!
TCP is stream oriented.
You can not expect that write() writes as much data as you told it to write, as well as you can not expect that read() reads as much data as you told it ro read.
This both put together means that to transfer N bytes via a socket the number of calls to read() does not necessarily needs to match the number of calls to write().
And following this conclusion the only thing the reader could know is how much it read from the moment on it was created.
The only two synchronisation points between reader and writer are the creation and the shutdown of the connection. The period one can call a session.
So if one wants to transfer multiple blocks of data having different sizes unknown to the reader during one session one is in the need to establish additional synchronisation points during the session, that make the read detect that a full block had been received.
Doing so is implementing some sort of protocol.
There are endless possiblities how the protcol could look like. The detailed design of the protocol depends on the use cases which shall be covered by the application.
Assuming only text data shall be transfered a simple protocol could be to terminate each data block by a \n.
The writer loops around write() until all data is sent and finally sends a \n.
The reader loops around read() until a \n had been received.
C strings are null terminated. You're not sending the zero byte that would terminate your string in your recieving buffer, so your printf will print out all characters it find until it reaches some zero byte. strlen returns length of string in number of characters, but without counting the zero byte at the end.
Try to change line in your client:
sendto(sockfd,mesg,strlen(mesg),0,(const struct sockaddr *)&servaddr,len);
Into:
sendto(sockfd,mesg,1+strlen(mesg),0,(const struct sockaddr *)&servaddr,len);

SIGPIPE error in a TCP based Concurrent Echo Cleint-Sever

I am new to network programming, and have been learning this by writing small programs that make use of the Socket API. Currently, I am writing a simple echo server, that uses fork to create a copy of it, as soon as it gets a connect request, this adds up as in improvement over the previous Iterative server (here). However, after I start the server and fire up the client, and type a message on its console, it quits unexpectedly. Running the program under Gdb shows that SIGPIPE was delivered. But as far as I know as the socket is still valid, a SIGPIPE shouldn't have occured. Any kind of help involved is appreciated.
Here is the client code
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#define MAXCOUNT 1024
int main(int argc, char* argv[])
{
int sfd,i;
struct sockaddr_in saddr;
char buff[MAXCOUNT];
char mesg[MAXCOUNT];
sfd = socket(AF_INET,SOCK_STREAM,0);
memset(&saddr,0,sizeof(saddr));
saddr.sin_family = AF_INET;
inet_pton(AF_INET,"127.0.0.1",&saddr.sin_addr);
saddr.sin_port = htons(5008);
connect(sfd,(struct sockaddr*) &saddr,sizeof(saddr));
fgets(buff,MAXCOUNT,stdin);
send(sfd,buff,strlen(buff),0);
if (recv(sfd,mesg,MAXCOUNT,0) == -1) {
perror("Nothing to read\n");
exit(1);
}
printf("%s\n",mesg);
exit(0);
}
Here is the server code
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#define MAXCOUNT 1024
int main(int argc, char* argv[])
{
int sfd,nsfd,cn;
pid_t c;
char buf[MAXCOUNT];
socklen_t clen;
struct sockaddr_in caddr,saddr;
sfd = socket(AF_INET,SOCK_STREAM,0);
memset(&saddr,0,sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
saddr.sin_port = htons(5008);
bind(sfd,(struct sockaddr*) &saddr,0);
listen(sfd,2);
for (; ;) {
clen = sizeof(caddr);
nsfd = accept(sfd,(struct sockaddr*) &caddr, &clen);
if( (c = fork()) == 0) {
close(sfd);
memset(buf,0,sizeof(buf));
cn = recv(nsfd,buf,sizeof(buf),0);
if ( cn == 0) {
perror("Reading from the client socket failed\n PROGRAM CRASH :\n");
exit(1);
}
buf[cn] = '\0';
send(nsfd,buf,strlen(buf),0);
close(nsfd);
exit(0);
}
}
return 0;
}
send(sfd,buff,strlen(buff),0);
if (recv(sfd,mesg,MAXCOUNT,0) == -1) {
perror("Nothing to read\n");
exit(1);
}
printf("%s\n",mesg);
The %s format specifier is for C-style strings, not arbitrary data. And since you throw away the return value from recv, you have no way to know how many bytes you got.
Your client also doesn't shut down the socket gracefully or make sure it has received all the data the server may send. So it's possible that you're triggering an abnormal termination. The server closes the connection when it's done sending, so the client should keep trying to receive until it detects that the connection has closed.

Resources