Because TCP is a stream protocol, so in the translation , there may have lots of sticky bags.
The passage offer two method to solve this problem.
1.We use the fixed length package to solve it.
2. We designed the protocol by ourselves , a struct wiht the head and body of the package. When we receive the message the need to receive the head of the message and then get the body of the package.
For the first solution:
Server:
/************************************************************************
> file name: echoserv.c
> Author: ma6174
> Mail: ma6174@163.com
> Created Time: Thu 29 Oct 16:38:57 2015
************************************************************************/
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#define ERR_EXIT(m) \
do \
{\
perror(m) ;\
exit(EXIT_FAILURE) ;\
}while(0)
//ssize_t signed integer size_t unsigned integer
ssize_t readn ( int fd , void *buf , size_t count ) // encapsulate readn as the function of read
{
size_t nleft = count ;
ssize_t nread ;
char *bufp ;
bufp = ( char *) buf ;
while ( nleft > 0 )
{
nread = read ( fd , bufp , nleft ) ;
if( nread < 0 )
{
if ( errno == EINTR ) // interrupted by signal , we don't think this occasion is not right
{
continue ;
}
return -1 ;
}
else if ( 0 == nread ) //peer closed
{
return count - nleft ;
}
bufp += nread ;
nleft -= nread ;
}
return count ;
}
ssize_t writen ( int fd , const void *buf ,size_t count )
{
size_t nleft = count ;
ssize_t nwritten ;
char *bufp ;
bufp = ( char * ) buf ;
while ( nleft > 0 )
{
if ( ( nwritten = write ( fd , bufp , nleft ) ) < 0 )
{
if ( errno == EINTR ) // just like the occasion in writen
{
continue ;
}
return -1 ;
}
else if ( 0 == nwritten ) // if 0 == nread , like nothing happened to write ...
{
continue ;
}
bufp += nwritten ;
nleft -= nwritten ;
}
return count ;
}
void do_service ( int conn )
{
char recvbuf[1024] ;
while(1)
{
memset ( recvbuf , 0 , sizeof(recvbuf)) ;
int ret = readn( conn , recvbuf , sizeof(recvbuf) ) ;
printf ("ret = %d\n" , ret ) ;
if ( 0 == ret )
{
printf ("client close") ;
break ;
}
else if ( -1 == ret )
{
ERR_EXIT ("read") ;
}
fputs ( recvbuf , stdout ) ;
writen ( conn , recvbuf , ret ) ;
}
}
int
main ()
{
int listenfd ;
if (( listenfd = socket ( PF_INET , SOCK_STREAM , IPPROTO_TCP )) < 0 )
{
ERR_EXIT("socket") ;
}
struct sockaddr_in servaddr ;
memset ( & servaddr , 0 , sizeof(servaddr ) ) ;
servaddr.sin_family = AF_INET ;
servaddr.sin_port = htons (5188) ;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY) ; //INTADDR_ANY == 0
//other two means to change the host address to network address
//servaddr.sin_addr.s_addr = inet_addr("127.0.0.1") ;
//inet_aton("127.0.0.1" , &servaddr.sin_addr) ;
/