如果两方都按固定的长度一次发送比如2000个字节,分多次发送,多次接收这个问题就不存在了.因为可能第一次已经把全部数据接收到缓冲区了,如果再分析包头,发现比2000还要长,就可以分批次接收,一直到数据全部接收完毕.
但看了下面的代码,我的疑问又来了:
#include "etcp.h"
int main( int argc, char **argv )
{
SOCKET s;
int n;
struct
{
u_int32_t reclen;
char buf[ 128 ];
} packet;
INIT();
s = tcp_client( argv[ 1 ], argv[ 2 ] );
while ( fgets( packet.buf, sizeof( packet.buf ), stdin )
!= NULL )
{
n = strlen( packet.buf );
packet.reclen = htonl( n );
if ( send( s, ( char * )&packet,
n + sizeof( packet.reclen ), 0 ) < 0 )
error( 1, errno, "send failure" ); //一次发送完了.
}
EXIT( 0 );
}
#include "etcp.h"
int main( int argc, char **argv )
{
struct sockaddr_in peer;
SOCKET s;
SOCKET s1;
int peerlen = sizeof( peer );
int n;
char buf[ 10 ];
INIT();
if ( argc == 2 )
s = tcp_server( NULL, argv[ 1 ] );
else
s = tcp_server( argv[ 1 ], argv[ 2 ] );
s1 = accept( s, ( struct sockaddr * )&peer, &peerlen );
if ( !isvalidsock( s1 ) )
error( 1, errno, "accept failed" );
for ( ;; )
{
n = readvrec( s1, buf, sizeof( buf ) );
if ( n < 0 )
error( 0, errno, "readvrec returned error" );
else if ( n == 0 )
error( 1, 0, "client disconnected\n" );
else
write( 1, buf, n );
}
EXIT( 0 ); /* not reached */
}
主要是readvrec函数, 请看如下:
int readvrec( SOCKET fd, char *bp, size_t len )
{
u_int32_t reclen;
int rc;
rc = readn( fd, ( char * )&reclen, sizeof( u_int32_t ) );
if ( rc != sizeof( u_int32_t ) )
return rc < 0 ? -1 : 0;
reclen = ntohl( reclen );
if ( reclen > len )
{
while ( reclen > 0 )
{
rc = readn( fd, bp, len );
if ( rc != len )
return rc < 0 ? -1 : 0;
reclen -= len;
if ( reclen < len )
len = reclen;
}
set_errno( EMSGSIZE );
return -1;
}
//超过长度就返回该字符串长度
rc = readn( fd, bp, reclen );
if ( rc != reclen )
return rc < 0 ? -1 : 0;
return rc;
}
int readn( SOCKET fd, char *bp, size_t len)
{
int cnt;
int rc;
cnt = len;
while ( cnt > 0 )
{
rc = recv( fd, bp, cnt, 0 );
if ( rc < 0 )
{
if ( errno == EINTR )
continue;
return -1;
}
if ( rc == 0 ) return len - cnt;
bp += rc;
cnt -= rc;
}
return len;
}
它这里recv了两次呀, 第一次 rc = readn( fd, ( char *
)&reclen, sizeof( u_int32_t ) );
这里最少也读了一次呀....
while ( reclen > 0 )
{
rc = readn( fd, bp, len );
这到底怎么理解recv呢??????????
发一个包,只能收一次。第二次再收到就是下一个包了。
确定接收缓冲大于收包的最大长度就行。
socket
接口一般都可能取出接收到的数据长度(bytes)。
不大于64K可以不分包,省事。
你没看一下程序吧,
它就是send了一次,却recv了两次呀..........
一个包没法分两次接?
我贴出来的例子就是分两次接的,第一次recv读长度,
第二次recv读内容...............
我是想问, 为什么可以这样????
开大缓冲一次接收完全部的数据然后慢慢拆分不就OK了,分2次接收增加了API的调用次数,降低了性能,没有任何实际意义。
>>这里最少也读了一次呀....
>>while ( reclen > 0 )
>> {
>> rc = readn( fd, bp, len );
从recv buffer中读取剩余len个字节
不知道lz是不是在这个地方有疑问,之前我发过一个帖子就误解lz的意思了。
"楠楠 写道:
"
> 接收方面,TCP协议没有数据边界,即一个发出的数据可能会在多次接收中才能全部接收完,而且多次发出的少量数据收可能在一次接收中全部收到了,为什么上面贴的源码可以接收两次,不明白.
发一个包 send(12+1024)
找到问题了,是我自己的程序处理上有些问题.....浪费了大家宝贵时间..sorry