Reputation: 1052
I was making a server using socket programming that echoes what the client says to him. But when I print out the message(send by client) and it's length, the message and it's length don't match. I am using printf to print.
What I basically want is to close the connection when the client types "exit". But strcmp("exit",clientmessage) is not working.
server code:
//for running type ./a.out anyportnumber
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
void *function(void *s)
{
int s1;
int n;
char rmsg[500];
s1 = *(int *)s;
while((n = read(s1,rmsg,499)) > 0) {
rmsg[n] = '\0';
printf("%s %d\n",rmsg,strlen(rmsg));
bzero(rmsg,499);
}
pthread_exit(NULL);
}
int main(int arrc,char *argv[])
{
struct sockaddr_in server,client;
int s1,len;
int s2;
int n;
int i = 0;
int port;
pthread_t t1;
char message[500];
port = atoi(argv[1]);
bzero((char *)&server,sizeof(server));
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
s1 = socket(AF_INET,SOCK_STREAM,0);
if(s1 == -1) {
perror("socket not created\n");
exit(1);
}
if(bind(s1,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
perror("socket not binded\n");
exit(1);
}
if(listen(s1,5) == -1) {
perror("unable to listen");
exit(1);
}
len = sizeof(struct sockaddr_in);
s2 = accept(s1,(struct sockaddr *)&client,&len);
pthread_create(&t1,NULL,function,(void *)&s2);
pthread_join(t1,NULL);
close(s2);
close(s1);
return 0;
}
client side input:
shivam@shivam-HP-Pavilion-15-Notebook-PC:~$ telnet localhost 8009
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hhh
jhiklmnop
Server side output:
shivam@shivam-HP-Pavilion-15-Notebook-PC:~/Study/chat$ ./a.out 8009
hhh
5
jhiklmnop
11
Edited code:
//for running type ./a.out anyportnumber
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
void *function(void *s)
{
int s1;
int n;
char rmsg[500];
s1 = *(int *)s;
char d[] = {'e','x','i','t','\0'};
while((n = read(s1,rmsg,499)) > 0) {
rmsg[n-2] = '\0';
if(strcmp(d,rmsg) == 0) {
write(s1,"bye",3);
close(s1);
}
rmsg[n-2] = '\n';
rmsg[n-1] = '\0';
write(s1,rmsg,strlen(rmsg));
bzero(rmsg,499);
}
pthread_exit(NULL);
}
int main(int arrc,char *argv[])
{
struct sockaddr_in server,client;
int s1,len;
int s2;
int n;
int i = 0;
int port;
pthread_t t1;
char message[500];
port = atoi(argv[1]);
bzero((char *)&server,sizeof(server));
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
s1 = socket(AF_INET,SOCK_STREAM,0);
if(s1 == -1) {
perror("socket not created\n");
exit(1);
}
if(bind(s1,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
perror("socket not binded\n");
exit(1);
}
if(listen(s1,5) == -1) {
perror("unable to listen");
exit(1);
}
len = sizeof(struct sockaddr_in);
s2 = accept(s1,(struct sockaddr *)&client,&len);
pthread_create(&t1,NULL,function,(void *)&s2);
pthread_join(t1,NULL);
close(s2);
close(s1);
return 0;
}
Upvotes: 0
Views: 475
Reputation: 283634
TCP is a stream-oriented protocol, there are no message boundaries. So you cannot write application logic that depends on the return value of read()
as you are doing.
Workarounds for this are length-prefixed strings, or sending the NUL terminator through the socket. You can dream up other mechanisms too, but the client must, within the data stream, tell the server where the message ends; the TCP layer won't do that.
Upvotes: 3
Reputation: 223739
Besides the characters the user is typing in, you're also getting a carriage return (0xd) and linefeed (0xa) character when the user presses the Enter key. That's why you're getting a number 2 larger than you might expect.
Upvotes: 0