0
votes

I'm trying to setup a client/server in C. I establish the connection, then I want to send an username and a pwd to the server, and the server has to reply confirming that he has received the usr/pwd. The problem is that both server and client exit as soon as they meet the "write" or "read" function. What should I do?

server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#include <signal.h>

void main(){
   int ds_sock;
   struct sockaddr_in my_addr;
   ds_sock=socket(AF_INET,SOCK_STREAM,0);

   memset(&my_addr,0,sizeof(my_addr));
   my_addr.sin_family=AF_INET;
   my_addr.sin_port=htons(25000);
   my_addr.sin_addr.s_addr=INADDR_ANY;

   if(bind(ds_sock,(struct sockaddr *)&my_addr,sizeof(my_addr))<0){
       printf("error in bind");
   }

   listen(ds_sock,2);
   int ds_sock_acc;
   struct sockaddr_in addr;
   size_t sin_size = sizeof(struct sockaddr_in);
   signal(SIGCHLD,SIG_IGN);
   while(1){
       if((ds_sock_acc=accept(ds_sock,(struct sockaddr *)&addr,&sin_size))<1){
           printf("error accept");
       }
    printf("connected");
    char usr[10];
    read(ds_sock,usr,10);
    char* confirm_usr;
    confirm_usr="Username received";
    write(ds_sock,confirm_usr,100);

    char pwd[10];
    read(ds_sock,pwd,10);
    char* confirm_pwd;
    confirm_pwd="Password received";
    write(ds_sock,confirm_pwd,100);
   }    
}

client.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>

void main(){
    int ds_sock;
    ds_sock = socket(AF_INET, SOCK_STREAM,0);

    int ret;
    struct sockaddr_in Eaddr;
    Eaddr.sin_family = AF_INET;
    Eaddr.sin_port = htons(25000);
    Eaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
    ret = connect(ds_sock,(struct sockaddr *)&Eaddr,sizeof(Eaddr));
    if(ret==-1){ 
        printf("error connect");
        exit(EXIT_FAILURE);
    }
    printf("connect OK");

    char usr[10];
    printf("Insert username");
    scanf("%s",usr);

    char pwd[12];
    printf("Insert password");
    scanf("%s",pwd);
    printf("%s",pwd);

    write(ds_sock,usr,10);  
    char usr_reply[100];
    read(ds_sock,usr_reply,100);
    printf("%s",usr_reply);

    write(ds_sock,pwd,12);
    char pwd_reply[100];
    read(ds_sock,pwd_reply,100);
    printf("%s",pwd_reply);
}
2
It's int main(void), mate. - Jens

2 Answers

4
votes

While the first answer is pretty complete, I wanted to add the 141 error is a SIGPIPE error. (check this in linux manual) You can strace your program to find the error code or implement errno and perror.

3
votes

You're accessing out of bounds, thus triggering undefined behavior in your write() call:

char* confirm_usr;
confirm_usr="Username received";
write(ds_sock,confirm_usr,100);

You're asking write() to send 100 bytes, but you only provide a pointer to 18 bytes. Reading any more than 18 from that location triggers undefined behavior. It would make more sense to use strlen() to avoid hardcoding the length:

const char *confirm_usr = "Username received";
write(ds_sock, confirm_usr, strlen(confirm_usr) + 1);

I made it + 1 to actually send the terminating '\0'-character, otherwise the other end has no way of figuring out when the string ends.

Also, you must check the return value of lots of calls, I/O can and will fail and just must deal with that.

It's also pretty strange that it looks as if both server and client begin by doing a read(), and that the server does I/O on a socket different from ds_sock_acc.