Segmentation fault trying to send message to client from server - c

I need to send a message to a client and then the client have to respond with an option. I get till the client and server connects, but both program end with "Segmentation Fault". Does anyone knows what this error means? Can someone give an idea to how to create a code that will make client and server interact. After receiving the option chosen by the client the server have to analyze it and send again a result to client.
My codes are:
Server
int
main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t len;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
time_t ticks;
char message[MAXLINE]="This is the server";
char temp_scale[2];
char recvdata[MAXLINE + 1];
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);/*----------------------------------------------------*/
servaddr.sin_port = htons(5555);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for ( ; ; )
{
len = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &len);
printf("Connection from %s, port %d\n",
Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
ntohs(cliaddr.sin_port));
snprintf(message, sizeof(message), "%s\r\n");
Writen(connfd, message, strlen(message));
while ( (n = read(connfd, recvdata, MAXLINE)) > 0)
{
recvdata[n] = 0; /* null terminate*/
if (fputs(recvdata, stdout) == EOF)
err_sys("fputs error");
}
if (n < 0)
err_sys("read error");
Close(connfd);
}
}
Client
int
main(int argc, char **argv)
{
int sockfd, rd;
socklen_t len;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr, cliaddr;
char scale[2];
/*if (argc != 2)
err_quit("usage: a.out <IPaddress>");*/
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
err_sys("socket error");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2])); /*port passed through command line*/
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) /*The client translates the server address, passed on the command line*/
err_quit("inet_pton error for %s", argv[1]);
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
err_sys("connect error");
len = sizeof(cliaddr);
Getsockname(sockfd, (SA *) &cliaddr, &len);
printf("Local Address is: %s\n",
Sock_ntop((SA *) &cliaddr, sizeof(cliaddr)));
printf("Iniciando read...\n");
while ( (rd = read(sockfd, recvline, MAXLINE)) > 0)
{
recvline[rd] = 0; /* null terminate*/
if (fputs(recvline, stdout) == EOF)
err_sys("fputs error");
}
if (rd < 0)
err_sys("read error");
printf("Enter option 'A' or 'B'");
send_scale(sockfd);
exit(0);
}
Thanks

Your server is probably faulting because of this:
snprintf(message, sizeof(message), "%s\r\n"); // <== no parameters
It is flat-out wrong. The snprintf() call has a format specifier that is expecting a char * to a null-terminated string, and you're passing it absolutely nothing. It is therefore grabbing a random value out of the stack, treating it as a pointer, and dereferencing it in attempt to fulfill the formatted request.
Without knowing the details of the API you're using (it clearly isn't standard BSD sockets just by the names alone) there isn't much more to go on.

Run your code in a debugger (for example gdb ./a.out) and find out in no time.

I don't know if it might help, but in C the null termination for strings is '\0', when you print your response:
recvdata[n] = 0; /* null terminate ----> this must be '\0'*/
if (fputs(recvdata, stdout) == EOF)
err_sys("fputs error");
you pad it whith a "0", so it will probably lead you to a segfault when fputs parse your string in order to print it.
Hope it helps!

Related

UDP socket: invalid argument error in sendto

I'm trying to write a simple UDP socket client-server program. The client machine is supposed to send a string to the server, that will answer with an ACK message.
Here's the implementation of the client side:
int main() {
message_send('L');
return EXIT_SUCCESS;
}
int message_send(char code) {
int sockfd;
ssize_t n;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr;
// Create an UDP socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket");
return -1;
}
// Setup the socket
memset((void *) &servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = (in_port_t) htonl(SERV_PORT);
if (inet_pton(AF_INET, SERVIP, &servaddr.sin_addr) <= 0) {
fprintf(stderr, "Error in inet_pton for %s\n", SERVIP);
exit(1);
}
// Send a test string
char *test = malloc(MAXLINE);
snprintf(test, MAXLINE, "SENDING:%c", code);
if (sendto(sockfd, &test, sizeof(test), 0, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
perror("sendto");
return -1;
}
// Get an answer from the server
n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
if (n < 0) {
perror("recvfrom");
exit(1);
} else if (n > 0) {
recvline[n] = 0; // Add ending character
if (fputs(recvline, stdout) == EOF) { // Print the received message in stdout
perror("fputs");
return -1;
}
}
return 0;
}
If I run this (whether the server machine is running or not) I get the following error:
sendto: Invalid argument
Why am I getting this error?
The most likely cause of the problem is the line
servaddr.sin_port = (in_port_t) htonl(SERV_PORT);
I'm guessing that gives you a bad port number (i.e. it will give you port 0 on a little endian machine). Port numbers are 16-bit, so you should be using htons.
Also, passing &test and sizeof(test) to sendto will send the pointer value over the network. To send the string, you need to use test and strlen(test)+1.

What's the data transformation pattern of when using tcp socket?

I have two server codes:
the first server: send the client a char each time until the string is finished
int
main(int argc, char **argv)
{
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[MAXLINE];
time_t ticks;
char temp[1];
int i = 0;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(9999); /* daytime server */
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for ( ; ; ) {
connfd = Accept(listenfd, (SA *) NULL, NULL);
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
for(i = 0; i < strlen(buff); i++)
{
temp[0] = buff[i];
Write(connfd, temp, strlen(temp));
}
Close(connfd);
}
}
the second server: send the client a string
int
main(int argc, char **argv)
{
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[MAXLINE];
time_t ticks;
char temp[1];
int i = 0;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(9999); /* daytime server */
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for ( ; ; ) {
connfd = Accept(listenfd, (SA *) NULL, NULL);
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
Write(connfd, buff, strlen(buff));
Close(connfd);
}
}
the client:receive the chars sent by the server
int
main(int argc, char **argv)
{
int sockfd, n;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr;
int count = 0;
if (argc != 2)
err_quit("usage: a.out <IPaddress>");
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
err_sys("socket error");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(9999); /* daytime server */
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
err_quit("inet_pton error for %s", argv[1]);
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
err_sys("connect error");
while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
recvline[n] = 0; /* null terminate */
count++;
if (fputs(recvline, stdout) == EOF)
err_sys("fputs error");
}
if (n < 0)
err_sys("read error");
printf("read time:%d\n", count);
exit(0);
}
the result is both of the output of variable count is 1. My question is why the first server's output is 1, I think the result should be strlen(buff) for the 1st server?
PS:I run the server and client on the same machine.
TCP is a stream protocol. As such the number of writes on one side will not cause the same amount of reads on the other side since the protocol doesn't preserve information about how the writes into the socket were made.
Usually, on the sender side there's a delay before a packet is sent in case you write more data to the socket so that more data can be stuffed into the same packet. One of the reasons for it is that a badly written server might flood the network with single byte packets.
On the receiver side, the protocol doesn't know why your data might have arrived as separate packets, it might have been split up because of the MTU, it might have been reassembled by some packet inspection software or appliance on the way, so whenever you read from your socket it will give you as much data as it can regardless of how it was sent to you.
On a local machine like in your setup it's likely that the client isn't even running while the server is writing, so even without buffering on the sender side it will not start reading until the server has written everything and therefore it will read everything in one go. Or not, you might be unlucky, your server gets preempted for long enough that the TCP implementation in your kernel thinks that there won't be any more data you'll be sending, send a single byte to the client, the client gets scheduled to run before the server runs again and the client will receive just one byte in the first read.

Message send, receiver not getting the message. Socket programing

I'm receiving a message from the client, comparing it and sending a message according to the result in the comparison. The server sends the message (apparently), but the client stays in the reading processes.
Server:
Waiting for incoming connections...Press Ctrl+C to end server
Connection from 127.0.0.1, port 54918 Message Recieved:c Random es 5
Into IFs 1er IF
void
result(int sockfd)
{
ssize_t n;
char buf[MAXLINE];
int temp;
time_t ticks;
int i;
again:
while ((n =read(sockfd, buf, MAXLINE)> 0))
{
buf[n] = '\0';
printf("Message Recieved:%s\n",buf);
srand (time(NULL));
temp = rand() % 15+1;
printf("Ramdom es %i\n",temp);
printf("Into IF\n");
if ((strncmp (buf,"A",1) == 0) || (strncmp (buf,"a",1) == 0))
{
snprintf(buf, sizeof(buf), "Option A chosen times %i on on %.24s\r\n", temp,ctime(&ticks));
Writen(sockfd, buf, n);
printf("1st IF\n");
}
else if ((strncmp (buf,"B",1) == 0) || (strncmp (buf,"b",1) == 0))
{
snprintf(buf, sizeof(buf), "Option B chosen times %i on on %.24s\r\n", temp,ctime(&ticks));
Writen(sockfd, buf, n);
printf("2nd IF\n");
}
else
{
printf("Incorrect Input");
Close(sockfd);
break;
}
}
if (n < 0 && errno == EINTR)
goto again;
else if (n < 0)
err_sys("read error");
printf("salio de funcion result\n");
}
int
main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t len;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
/*char message[MAXLINE];*/
char recvline[MAXLINE + 1];
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);/*----------------------------------------------------*/
servaddr.sin_port = htons(5678);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
printf("Server is running on 127.0.0.1, listening on port 5678\n");
printf("\n");
printf("Waiting for incoming connections...Press Ctrl+C to end server\n");
for ( ; ; )
{
len = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &len);
/*Client connects to server*/
printf("\n");
printf("Connection from %s, port %d\n",
Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
ntohs(cliaddr.sin_port));
result(connfd);
Close(connfd);
}
}
Client:
Connect... Local Address is: 127.0.0.1:54918
Starting read...
Enter Option A or B: b
void
get_temp(FILE *fp, int sock)
{
char sendline[MAXLINE], recvline[MAXLINE];
while (Fgets(sendline, MAXLINE, fp) != NULL) {
Writen(sock, sendline, strlen(sendline));
if (Readline(sock, recvline, MAXLINE) == 0)
err_quit("Server Terminated Prematurely");
Fputs(recvline, stdout);
}
}
int
main(int argc, char **argv)
{
int sockfd, n;
socklen_t len;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr, cliaddr;
char scale[2];
if (argc != 3)
err_quit("usage: a.out <IPaddress>");
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
err_sys("socket error");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2]));
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
err_quit("inet_pton error for %s", argv[1]);
printf("Connect...\n");
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
err_sys("connect error");
len = sizeof(cliaddr);
Getsockname(sockfd, (SA *) &cliaddr, &len);
printf("Local Address is: %s\n",
Sock_ntop((SA *) &cliaddr, sizeof(cliaddr)));
printf("Starting read...\n");
printf("Enter option A or B: ");
get_temp(stdin, sockfd);
exit(0);
}
Thanks.
Stop coding and write a protocol specification. The specification should specify, at the byte level, what information is exchanged and how. The way you're doing it now, it's impossible for you code to be "right" or "wrong" because there is no specification for it to comply with or not comply with.
The most important thing to cover in the protocol specification is whether you have a "message" and if so, how each side finds the beginning and end of them. You can use closing the connection as a message boundary. You can use a delimiter (such as a zero byte or a newline) as a message boundary. You can prefix each message with its length.
But without a specification, your server and client will only agree on who does what, when, and how by luck.

Client does not receive message form server

I'm sending a message (a greeting) from a server to a client. The server sends the data but the client is not receiving it and then the server jumps to a read because client have to reply with an input of the user. Can you tell me why I never receive the greeting message?
Server:
int
main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t len;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
time_t ticks;
char message[50];
char temp_scale[2];
char recvdata[MAXLINE + 1];
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);/*----------------------------------------------------*/
servaddr.sin_port = htons(5678);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
printf("Listening on port 5678...Press Ctrl+C to end server\n");
printf("Waiting for incoming connections...\n");
for ( ; ; )
{
len = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &len);
/*Client connects to server*/
printf("Connection from %s, port %d\n",
Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
ntohs(cliaddr.sin_port));
snprintf(message, sizeof(message), "%s\r\n", "Welcome!");
Writen(connfd, message, strlen(message));
while ( (n = read(connfd, recvdata, MAXLINE)) > 0)
{
recvdata[n] = 0; /* null terminate*/
if (fputs(recvdata, stdout) == EOF)
err_sys("fputs error");
}
if (n < 0)
err_sys("read error");
Close(connfd);
}
}
Client:
int
main(int argc, char **argv)
{
int sockfd, n;
socklen_t len;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr, cliaddr;
char scale[2];
/*if (argc != 2)
err_quit("usage: a.out <IPaddress>");*/
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
err_sys("socket error");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2])); /*port passed through command line*/
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) /*The client translates the server address, passed on the command line*/
err_quit("inet_pton error for %s", argv[1]);
printf("Connect...\n");
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
err_sys("connect error");
len = sizeof(cliaddr);
Getsockname(sockfd, (SA *) &cliaddr, &len);
printf("Local Address is: %s\n",
Sock_ntop((SA *) &cliaddr, sizeof(cliaddr)));
while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
recvline[n] = 0; /* null terminate */
if (fputs(recvline, stdout) == EOF)
err_sys("fputs error");
}
if (n < 0)
err_sys("read error");
printf("Enter the thermal Unit ('C' Celsius, 'F' Farehnheit: ");
send_data(sockfd);
exit(0);
}
Thanks!

How to compare data sent by client in server C programing

I want to send a option from the client to a server. The server have to do some comparisons and send a string back to the client. I can receive the data from the client, but my server crashes in the moment of comparison (it gets to the else with the "error input" and ends the connection). Can someone tell me what I'm doing wrong?
Incorrect Inputclose error: Bad file descriptor
Program exited with code 01.
Server:
void
result(int sockfd)
{
ssize_t n;
char buf[MAXLINE];
int temp;
time_t ticks;
again:
while ((n =read(sockfd, buf, MAXLINE)> 0))
{
temp = rand() % 22;
if (buf=="A\n" || buf=="a\n")
{
snprintf(buf, sizeof(buf), "You option is number is -%i, time is %.24s\r\n", temp,ctime(&ticks));
Writen(sockfd, buf, n);
}
if (buf=="B\n" || buf=="f\")
{
snprintf(buf, sizeof(buf), "You option is number is -%i, time is %.24s\r\n", temp,ctime(&ticks));
Writen(sockfd, buf, n);
}
else
{
printf("Incorrect Input");
Close(sockfd);
}
}
if (n < 0 && errno == EINTR)
goto again;
else if (n < 0)
err_sys("read error");
}
int
main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t len;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
char recvline[MAXLINE + 1];
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);/*----------------------------------------------------*/
servaddr.sin_port = htons(5678);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
printf("EDMTS is running on 129.128.4.80, listening on port 5678\n");
printf("\n");
printf("Waiting for incoming connections...Press Ctrl+C to end server\n");
for ( ; ; )
{
len = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &len);
/*Client connects to server*/
printf("\n");
printf("Connection from %s, port %d\n",
Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
ntohs(cliaddr.sin_port));
result(connfd);
Close(connfd);
printf("Conexion cerrada...Esperando siguiente cliente\n");
}
}
Client
void
get_temp(FILE *fp, int sock)
{
char sendline[MAXLINE], recvline[MAXLINE];
while (Fgets(sendline, MAXLINE, fp) != NULL) {
Writen(sock, sendline, strlen(sendline));
if (Readline(sock, recvline, MAXLINE) == 0)
err_quit("Server Terminated Prematurely");
Fputs(recvline, stdout);
}
}
int
main(int argc, char **argv)
{
int sockfd, n;
socklen_t len;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr, cliaddr;
char scale[2];
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
err_sys("socket error");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2]));
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
err_quit("inet_pton error for %s", argv[1]);
printf("Connect...\n");
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
err_sys("connect error");
len = sizeof(cliaddr);
Getsockname(sockfd, (SA *) &cliaddr, &len);
printf("Local Address is: %s\n",
Sock_ntop((SA *) &cliaddr, sizeof(cliaddr)));
printf("Enter option A or B): ");
get_temp(stdin, sockfd);
exit(0);
}
When I run the debugger to find out my variables, I find:
Breakpoint 1, result (sockfd=7) at servertest.c:236 236
printf("Random es %i\n",temp);
(gdb) p buf
$1 = "A\n", '\0' , "\203\217��", '\0' ,
"h\206��h\206��\204\210������#���\000\000\000\000�\206����߷\020\207��#���",
'\0' ,
"������������\000\000\000\000\000\000\000\000�\017��", '\0' , "h\206��", '\0' ,
"\001\000\000\000\000\000\000\000�\207��", '\0' ,
"����\t\000\000\000#���\030���\000\000\000\000h\206��\003", '\0'
, "\n\000\000\000g\206��", '\0' ,
" "...
(gdb) p temp
$2 = 17
Thank you very much
First of all, you can't compare C strings using == (you will compare pointer adresses, and the address of buf[0] and the address of your static string "a\n" will certainly not be equal. To compare the strings, use strncmp().
Your crash happens because after you call Close(), the read() function is called again on the socket file descriptor. To remove the crash, put a break; after the Close(), like so:
else
{
printf("Incorrect Input");
Close(sockfd);
break;
}
Also, you are closing the socket twice. First here:
// void result(int sockfd)
else
{
printf("Incorrect Input");
Close(sockfd); // <<<
}
Then here:
// int main(int argc, char **argv)
Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
ntohs(cliaddr.sin_port));
result(connfd);
Close(connfd); // <<<
printf("Conexion cerrada...Esperando siguiente cliente\n");

Resources