Why is strncmp not comparing? Socket programing C - c

I'm trying to parse the received data from a client in a server. The server have to send back a message according to what the client sent before. But I can not make the strncmp function compare the strings. It always get to the else and my server close the conection. Also my client stays connected and print in screen the option I typed.
Please need help to understand what is wrong!
Thanks!
Incorrect Inputclose error: Bad file descriptor
Program exited with code 01.
void
result(int sockfd)
{
ssize_t n;
char buf[MAXLINE];
int temp;
time_t ticks;
int i;
again:
while ((n =read(sockfd, buf, 15)> 0))
{
buf[n] = '\0';
printf("Message Recieved:%s\n",buf);
srand (time(NULL));
temp = rand() % 15+1;
printf("Ramdom es %i\n",temp);
if ((strncmp (buf,"A",1) == 0) || (strncmp (buf,"a",1) == 0))
{
snprintf(buf, sizeof(buf), "You chose option A -%i times on %.24s\r\n", temp,ctime(&ticks));
Writen(sockfd, buf, n);
}
if ((strncmp (buf,"B",1) == 0) || (strncmp (buf,"b",1) == 0))
{
snprintf(buf, sizeof(buf), "You chose option B -%i times on on %.24s\r\n", temp,ctime(&ticks));
Writen(sockfd, buf, n);
}
else
{
printf("Incorrect Input");
Close(sockfd);
break;
}
}
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 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("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);
}
}

With a little logic
if ((strncmp (buf,"B",1) == 0) || (strncmp (buf,"b",1) == 0))
{
snprintf(buf, sizeof(buf), "You chose option B -%i times on on %.24s\r\n", temp,ctime(&ticks));
Writen(sockfd, buf, n);
}
else
{
printf("Incorrect Input");
Close(sockfd);
break;
}
Is where the else lies.
I.e.
it gets run when after it is hits this:
if ((strncmp (buf,"A",1) == 0) || (strncmp (buf,"a",1) == 0))
{
snprintf(buf, sizeof(buf), "You chose option A -%i times on %.24s\r\n", temp,ctime(&ticks));
Writen(sockfd, buf, n);
}
BTW use toupper http://www.cplusplus.com/reference/cctype/toupper/
i.e.
if ('B' == toupper(buf[0]) ...
Just add another ELSE!

Related

C server socket's read function writing dirty buffer

I have the following C server and client:
SERVER
int main(int argc, char **argv) {
int listenfd, connfd, n;
struct sockaddr_in servaddr;
char recvline[1025];
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket Error");
exit(1);
}
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(1024);
if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
perror("Bind Error");
exit(1);
}
if (listen(listenfd, 1024) < 0) {
perror("Listen Error");
exit(1);
}
while(1) {
printf("Waiting connection...\n");
if ((connfd = accept(listenfd, (struct sockaddr *) NULL, NULL)) < 0) {
perror("Accept Error");
exit(1);
}
printf("Waiting for input.\n");
while ((n = read(listenfd, recvline, sizeof(recvline))) > 0) {
recvline[n] = '\0';
if (fputs(recvline, stdout) == EOF) {
fprintf(stderr,"fputs Error\n");
exit(1);
}
}
printf("Read string: %s", recvline);
close(connfd);
}
}
CLIENT
int main(int argc, char **argv) {
int sockfd, connfd, n;
struct sockaddr_in servaddr;
char buff[1025], matricola[15];
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket Error");
exit(1);
}
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(1024);
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0) {
fprintf(stderr,"inet_pton Error for %s\n", argv[1]);
exit (1);
}
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
fprintf(stderr,"Connect Error\n");
exit(1);
}
printf("Matricola: ");
fflush(stdin);
scanf("%s", matricola);
strcpy(buff, matricola);
if (write(sockfd, buff, strlen(buff)) != strlen(buff)) {
perror("Write Error");
exit(1);
}
close(connfd);
}
I'm under Linux, I can start the server correctly from terminal that starts listening, but when I open another terminal instance and start the client, the server automatically executes the rest of the code and prints Read string: ### (random characters like dirty buffer). Is this because the server is not waiting for the client to write? What am I doing wrong in this code?
What I tought was that the server didn't wait for the client to write something, so I tried to add a sleep(10) before the server's read command, but nothing changes.
EDIT: I edited the read function from
n = read(listenfd, recvline, strlen(recvline) + 1)) > 0
to
n = read(listenfd, recvline, sizeof(recvline))) > 0
But still it doesn't fix the issue.
Change your inner while cycle to read from the connected file descriptor, not the listening file descriptor, like this:
while ((n = read(connfd, recvline, strlen(recvline) + 1)) > 0) {
recvline[n] = '\0';
if (fputs(recvline, stdout) == EOF) {
fprintf(stderr,"fputs Error\n");
exit(1);
}
}
This line
while ((n = read(listenfd, recvline, sizeof(recvline))) > 0) {
tries to read from the listening socket. This does not make sense.
You need to read from the accepted socket. So it should be:
while ((n = read(connfd, recvline, sizeof(recvline))) > 0) {
Moreover it should be
while ((n = read(connfd, recvline, sizeof(recvline) - 1)) > 0) {
as after the read() you do
recvline[n] = '\0';
For the OP's source if you'd have read sizeof recvline bytes recvline[n] would address one behind the last element of recvline.

Server does not get into the if statement, it structs. Socket programming in C

I want to compare some data that the client sends to a server. But my server got stuck after the random function in my result function. It does nos printf (printf("Into IF");) or get into the ifs, why is this?
Waiting for incoming connections...Press Ctrl+C to end server
Connection from 127.0.0.1, port 60697 Message Recieved:c Ramdom es 12
My code:
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");
if ((strncmp (buf,"A",1) == 0) || (strncmp (buf,"a",1) == 0))
{
snprintf(buf, sizeof(buf), "You choose -%i tymes optin A on %.24s\r\n", temp,ctime(&ticks));
Writen(sockfd, buf, n);
}
else if ((strncmp (buf,"B",1) == 0) || (strncmp (buf,"b",1) == 0))
{
snprintf(buf, sizeof(buf), "You choose -%i tymes optin B on on %.24s\r\n", temp,ctime(&ticks));
Writen(sockfd, buf, n);
}
else
{
printf("Incorrect Input");
Close(sockfd);
break;
}
}
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 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);
}
}
Thanks!
To print the printf add a "\n" (linefeed) so that terminal flushes and displays it. There are several occasions in your code where a \n will help your debug-printfs coming out.
This answers "why does printf does not printf". I think this is not your real problem though.

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.

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

passing argument 1 of ‘strncmp’ makes pointer from integer without a cast C programing

I want to compare some data that the client sends to a server. Bout i have this error when I use strncmp t compare what I read from the socket and the strings I'm using to compare. Can someone tell me why is this error?
warning: passing argument 1 of ‘strncmp’ makes
pointer from integer without a cast
Server:
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() % 40+1;
printf("Ramdom es %i\n",temp);
if ((strncmp (buf[0],"Axx",1) == 0) || (strncmp (buf[0],"axx",1) == 0))
{
snprintf(buf, sizeof(buf), "Option A choosen in %i on %.24s\r\n", temp,ctime(&ticks));
Writen(sockfd, buf, n);
}
if ((strncmp (buf[0],"Bxx",1) == 0) || (strncmp (buf[0],"bxx",1) == 0))
{
snprintf(buf, sizeof(buf), "Option B choosen in %i on %.24s\r\n", temp,ctime(&ticks));
Writen(sockfd, buf, n);
}
else
{
printf("Incorrect Input");
Close(sockfd);
break;
}
}
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 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("EDMTS 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);
}
}
Thank you very much.
strncmp expects a const char* as first argument whereas you pass just a char.
Change it to:
if ((strncmp (buf,"Bxx",1) == 0) || (strncmp (buf,"bxx",1) == 0))
You should pass not character (buf[0]) but pointer to character (buf for example) for comparison.
buf[0] is a char, but strncmp expects a char*. Instead of
strncmp (buf[0],"Axx",1)
make it
strncmp (buf,"Axx",1)
etc.
But, if you pass 1 as the length parameter to strncmp, you could also just check
if (buf[0] == 'A' || buf[0] == 'a') // resp. 'B', 'b'
and avoid the function call.

Resources