我的同事和我说,传说中神乎其神的程序员很多,但未必有很多人会写Socket编程,我曾经不以为然。我曾经看过不少Socket编程的Demo,也就认为Socket编程也就这样了。但或许我错了。我的同事告诉我,socket编程和高效socket编程是两码事,我也不以为然。我曾经很鄙视微软RPC。所有的一切一切证明我都错了。
错误的原因在于我看到了ACE的源码。下面是一个片断:
ssize_t
ACE
::
recv_n_i
(
ACE_HANDLE
handle
,
void
*
buf
,
size_t
len
,
int
flags
,
size_t
*
bt
)
{
size_t
temp
;
size_t
&
bytes_transferred
=
bt
== 0 ?
temp
: *
bt
;
ssize_t
n
;
for
(
bytes_transferred
= 0;
bytes_transferred
<
len
;
bytes_transferred
+=
n
)
{
// Try to transfer as much of the remaining data as possible.
n
=
ACE_OS
::
recv
(
handle
,
(char *) buf + bytes_transferred,
len - bytes_transferred,
flags
);
// Check EOF.
if
(
n
== 0)
return
0;
// Check for other errors.
if
(
n
== -1)
{
// Check for possible blocking.
if
(
errno
==
EWOULDBLOCK
)
{
// Wait for the blocking to subside.
int
result
=
ACE
::
handle_read_ready
(
handle
,
0);
// Did select() succeed?
if
(
result
!= -1)
{
// Blocking subsided. Continue data transfer.
n
= 0;
continue
;
}
}
// Other data transfer or select() failures.
return
-1;
}
}
return
static_cast
<
ssize_t
> (
bytes_transferred
);
}
如果收到0,代表对端主动断开连接,这时候返回0;但是如果是-1的话,就需要仔细斟酌了。ACE没有武断地返回,而是检查了错误原因。如果Socket没有Block住的话,就会返回error,原因是
EWOULDBLOCK;这时候ACE试图select,看看能不能读,如果可以读的话,就会继续读取。
如果以前我写Socket程序,我会这么写么?不会。因为我没有对Socket掌握的那么透彻,我相信也许很多传奇也不会写。
顺被说一句很可笑的事情,我以前不知道怎么处理网络收包错误导致网络包字节错位的问题,现在总算想明白了,直接把socket断开重连就可以了。以前,中兴的彩铃平台就是这样做的,我当时没有领会这样的好处。