testermaster testermaster - 1 month ago 9
C Question

write socket causes "program exited with code 141" in C

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);
}

Answer

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.

Comments