我们来看这样一个问题, 在udp socket编程中, sendto连续三次发送10个字节的数据“0123456789”, 此时对端连续三次调用recvfrom函数来接收, 每次接收2个字节, 请问是接收到“01” “23” “45” 还是 “01” “01” “01” ? 我们先来看看程序:
服务端:
#include
#include
#include
#include
#include
#include
#include
int main()
{
struct sockaddr_in srvAddr;
bzero(&srvAddr,sizeof(srvAddr));
srvAddr.sin_family = AF_INET;
srvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
srvAddr.sin_port = htons(8888);
int srvAddrLen = sizeof(srvAddr);
int iSock = socket(AF_INET, SOCK_DGRAM, 0); // udp
bind(iSock, (struct sockaddr *)&srvAddr, sizeof(srvAddr));
while(1)
{
getchar();
char szBuf[3] = {0};
int iRet = recvfrom(iSock, szBuf, sizeof(szBuf) - 1, 0, (struct sockaddr *)&srvAddr, (socklen_t*)&srvAddrLen);
printf("msg from client [%s], iRet is %d\n", szBuf, iRet);
}
close(iSock);
return 0;
}
客户端为:
#include
#include
#include
#include
#include
#include
#include
int main()
{
struct sockaddr_in srvAddr;
bzero(&srvAddr, sizeof(srvAddr));
srvAddr.sin_family = AF_INET;
srvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
srvAddr.sin_port = htons(8888);
int iSock = socket(AF_INET, SOCK_DGRAM, 0); // udp
while(1)
{
printf("press enter to send data\n");
getchar();
char szBuf[128] = {0};
snprintf(szBuf, sizeof(szBuf), "0123456789");
printf("send size is %d\n", strlen(szBuf));
sendto(iSock, szBuf, strlen(szBuf), 0, (struct sockaddr *)&srvAddr, sizeof(srvAddr));
}
close(iSock);
return 0;
}
先启动服务端, 再启动客户端。
客户端连续三次给服务端发送数据后, 客户端结果为:
xxxxxx:~/network> ./client
press enter to send data
send size is 10
press enter to send data
send size is 10
press enter to send data
send size is 10
press enter to send data
然后服务端三次接收, 结果为:
xxxxxx:~/network> ./server
msg from client [01], iRet is 2
msg from client [01], iRet is 2
msg from client [01], iRet is 2
咦, “23456789”跑哪里去了?
这就是涉及到udp的数据报传输方式了, 发几次就需要几次来收, 如果收包长度不过, 多的会被丢弃, 而不会在下次recvfrom的时候取到。
所以, 在使用udp socket编程的时候, 务必注意这点, buffer太小, 容易导致概率性问题(长包接收不完整而出错, 注意, 此时recvfrom函数并不会返回一个错误的值)。