TCP 粘包问题处理[1] ( the solution of sticky package problem of TCP )

本文介绍了TCP协议中可能出现的粘包现象,并提出了两种解决方法:一是采用固定长度的数据包;二是自定义协议,包含头部和消息体,先接收头部确定消息长度再获取消息体。
摘要由CSDN通过智能技术生成

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) ;
	
	/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值