Re: echo client/server give problems if array sizes are different
- From: Brice Rebsamen <brice.rebsamen@xxxxxxxxx>
- Date: Tue, 10 Jun 2008 23:11:09 -0700 (PDT)
On Jun 11, 12:17 pm, Brice Rebsamen <brice.rebsa...@xxxxxxxxx> wrote:
On Jun 5, 6:08 pm, David Schwartz <dav...@xxxxxxxxxxxxx> wrote:
On Jun 5, 2:34 am, arnuld <sunr...@xxxxxxxxxxxxxxxx> wrote:
char arrc[ARRSIZE];
memset( arrc, '\0', strlen(arrc) );
First bug. In the call to memset, 'arrc' contains random junk. It does
not contain a C-style string yet. Why do you pass it to 'strlen'?
while( (recv_flag = recv( sockfd, arrc, BUFFSIZE, 0)) != -1 )
{
printf("\n---------------:: %s\n", arrc);
At this point, 'arrc' contains some random bytes you received. It does
not contain a C-style string yet. Why do you try to print it with
'%s'?
if( send(sockfd, arrc, BUFFSIZE, 0 ) == -1 )
At this point, recv_flag contains the number of bytes received. Why
are you passing some other number to 'send' as the number of bytes to
send?
I remember you saying your program would receive a *line* and then
send a *line*? Where's the code to check when you have a line? Did you
forget to actually implement your protocol completely?!
/* a simple client to send a string to server
* and then recieving same string back.
Ahh, it's a string, not a line? Which is it? Take a step back and
define your protocol with a specification. Otherwise, when you have
problems like this, it's impossible to know what's right.
char arrc[ARRSIZE];
memset( arrc, '\0', strlen(arrc) );
Same bug. Do you know the difference between an array of characters
and a string? (The answer: a string must end with a 0 bytes.) At this
point 'arrc' is not a string (nobody put any zero byte anywhere), so
it is an error to pass it to 'strlen'.
while( fgets(arrc, ARRSIZE, stdin) )
{
if( send( sockfd, arrc, ARRSIZE, 0 ) == -1 )
Whoa! You only want to send the bytes you got from 'fgets'. Not the
whole array!
if( recv( sockfd, arrc, ARRSIZE, 0) == -1 )
{
fprintf(stderr, "RECV() error!\n");
exit( EXIT_FAILURE );
}
fputs( arrc, stdout );
You receive some number of bytes into 'arrc', you have no idea how
many. You do not have a C-style string, since there's no terminating
zero byte. You *cannot* pass this to 'fputs'.
It looks like three classic errors:
1) A use of TCP without designing and specifying a protocol on top of
TCP.
2) A use of TCP with an assumption that bytes of data are somehow
glued together by TCP. (This is why you need '1', because they're
not.)
3) A consistent confusion between arrays of characters of known length
and C-style strings.
DS
2) A use of TCP with an assumption that bytes of data are somehow
glued together by TCP. (This is why you need '1', because they're
not.)
The bytes may arrive in small chunks so you have to repeat the read
call until all bytes are here. Meaning that you should check for a
termination character, i.e. '\0'. TCP guarantees that packets all
arrive in the right order but doesn't guarantee that a message arrive
in one chunk (even if small messages might very often arrive in one
chunk).
I tried to modify the posted code to create a multi threaded server
instead of a multi processed one (see code below). However I don't
understand why when one of the clients exits (CTRL-C) it also kills
the server.
Here is a code for the server part.
#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 <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#define SERVER_IP "127.0.0.1"
#define BUFFSIZE 101
#define MAX_CONNECTION 25
void *echo_back( void * );
int main( int argc, char** argv )
{
int server_fd, accept_fd, my_port;
struct sockaddr_in servaddr;
pthread_t tid;
memset( &servaddr, '\0', sizeof(servaddr) );
if( argc == 2 )
{
my_port = atoi( argv[1] );
}
else
{
fprintf( stderr, "USAGE: ./file PORT\n");
exit( EXIT_FAILURE );
}
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons( my_port );
inet_aton( SERVER_IP, &(servaddr.sin_addr) );
if( -1 == (server_fd = socket(PF_INET, SOCK_STREAM, 0)) )
{
fprintf( stderr, "SOCKET() error\n" );
exit( EXIT_FAILURE );
}
if( -1 == bind( server_fd, (struct sockaddr*) &servaddr,
sizeof( struct sockaddr )) )
{
fprintf( stderr, "BIND() error\n" );
exit( EXIT_FAILURE );
}
printf("bind()\n");
if( -1 == listen( server_fd, MAX_CONNECTION ))
{
fprintf( stderr, "LISTEN() error\n" );
exit( EXIT_FAILURE );
}
printf("listen()\n");
/* now lets see what client has to say */
for( ; ; )
{
if( (accept_fd = accept(server_fd, 0, 0)) == -1 )
{
fprintf( stderr, "ACCEPT() error\n" );
exit( EXIT_FAILURE );
}
printf( " accept()\n");
if( pthread_create(&tid,0,echo_back,&accept_fd)!=0 )
{
fprintf( stderr, "pthread_create() error\n" );
exit( EXIT_FAILURE );
}
printf( " pthread_create()\n");
}
return 0;
}
void * echo_back( void* sockfd_ )
{
int nBytes, sockfd;
char arrc[BUFFSIZE];
sockfd = *((int *)sockfd_);
memset( arrc, '\0', BUFFSIZE );
while( (nBytes = recv( sockfd, arrc, BUFFSIZE, 0)) != -1 )
{
if( nBytes==0 )
continue;
printf("\n---------------:: %s\n", arrc);
if( send(sockfd, arrc, BUFFSIZE, 0 ) == -1 )
{
fprintf( stderr, "SEND() error\n" );
close(sockfd);
return NULL;
}
memset( arrc, '\0', BUFFSIZE );
}
if( nBytes == -1 )
{
fprintf( stderr, "RECV() error\n" );
close(sockfd);
return NULL;
}
return NULL;
}
Here is the client part (same as above, except that I fixed the usage
of string arrays)
/*
* A simple client to send a string to server
* and then recieving same string back.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MY_SERVER "127.0.0.1"
#define BUFFSIZE 101
int main( int argc, char** argv )
{
int sockfd, MY_PORT;
struct sockaddr_in client_str;
char arrc[BUFFSIZE];
memset( arrc, '\0', strlen(arrc) );
if( argc == 2 )
{
MY_PORT = atoi( argv[1] );
}
else
{
fprintf(stderr, "I expect the port number as argument\n");
exit( EXIT_FAILURE );
}
if( (sockfd = socket( PF_INET, SOCK_STREAM, 0 ) ) == -1 )
{
fprintf(stderr, "SOCKET ERROR: can not create socket\n");
exit( EXIT_FAILURE );
}
client_str.sin_family = AF_INET;
client_str.sin_port = htons(MY_PORT);
client_str.sin_addr.s_addr = inet_addr( MY_SERVER );
memset( client_str.sin_zero, '\0', sizeof( client_str.sin_zero ) );
if( connect( sockfd, (struct sockaddr*) &client_str, sizeof( struct
sockaddr)) == -1 )
{
fprintf(stderr, "CONNECT() error\n");
exit( EXIT_FAILURE );
}
while( fgets(arrc, BUFFSIZE, stdin) )
{
if( send( sockfd, arrc, strlen(arrc), 0 ) == -1 )
{
fprintf(stderr, "SEND() error!\n");
exit( EXIT_FAILURE );
}
memset( arrc, '\0', BUFFSIZE );
if( recv( sockfd, arrc, BUFFSIZE, 0) == -1 )
{
fprintf(stderr, "RECV() error!\n");
exit( EXIT_FAILURE );
}
fputs( arrc, stdout );
memset( arrc, '\0', BUFFSIZE );
}
return 0;
}
.
- Follow-Ups:
- Re: echo client/server give problems if array sizes are different
- From: Barry Margolin
- Re: echo client/server give problems if array sizes are different
- References:
- echo client/server give problems if array sizes are different
- From: arnuld
- Re: echo client/server give problems if array sizes are different
- From: David Schwartz
- Re: echo client/server give problems if array sizes are different
- From: Brice Rebsamen
- echo client/server give problems if array sizes are different
- Prev by Date: Re: echo client/server give problems if array sizes are different
- Next by Date: Re: echo client/server give problems if array sizes are different
- Previous by thread: Re: echo client/server give problems if array sizes are different
- Next by thread: Re: echo client/server give problems if array sizes are different
- Index(es):
Relevant Pages
|