在这上面花了一周多,先是思路上的致命错误,导致浪费较多时间,不过调整下很快的完成了自己所需要的代码。
期间碰到的几个比较大的问题自己做下记录:
1、bind函数的理解错误,这个一般是在服务端用来绑定端口,而我一直以为可以用函数inet_addr()指定接收的IP,其实这里只是假如你有双网卡的时候,有需要可以绑定其中一个IP,htonl(INADDR_ANY)或0最实在。
贴下一段初始化的代码
bzero(&socket_info.server_addr, sizeof(socket_info.server_addr));
socket_info.server_addr.sin_family = AF_INET;
socket_info.server_addr.sin_addr.s_addr = 0; //htonl(INADDR_ANY);
socket_info.server_addr.sin_port = htons(PORT);
socket_info.descriptor_TCP_server = socket(AF_INET, SOCK_STREAM , 0);//UDP: SOCK_DGRAM TCP:SOCK_STREAM
if (socket_info.descriptor_TCP_server == -1)
{
perror ("socket call failed");
exit(errno);
}
if(bind(socket_info.descriptor_TCP_server, //将套接口和进程联系起来
(struct sockaddr *)&socket_info.server_addr ,
sizeof(socket_info.server_addr)) == -1 )
{
perror("bind TCP");
exit(errno);
}
2、TCP与UDP的选择使用上,UDP速度快不管数据完整不,TCP其实可以理解成UDP加检测数据(个人观点)。而我需要检验数据,但是数据传输肯定是要用UDP,所以一开始是想纯用UDP实现,当然需要自己写检验的相关代码,后来发现还要来回连接,麻烦哦...咨询了一同事的思路:TCP+UDP,TCP管连接和来回的要求重发数据等操作,而UDP则只管发送数据,效果感觉还行。至少比用纯UDP做实在。
3、TCP的connect函数
int connect_server(void)
{
int savefl, ret;
fd_set set;
struct timeval tival;
tival.tv_sec = 10;
tival.tv_usec = 0;
//设置为非阻塞
savefl = fcntl(socket_info.socket_descriptor_TCP, F_GETFL);
if( fcntl(socket_info.socket_descriptor_TCP, F_SETFL, savefl | O_NONBLOCK) == -1)
{
perror("trying to set input socket to non-blocking");
return 1;
}
//连接成功
if (connect(socket_info.socket_descriptor_TCP,
(struct sockaddr *)&socket_info.address,
sizeof(socket_info.address)) == 0)
{
if( fcntl(socket_info.socket_descriptor_TCP, F_SETFL, savefl) == -1) //设置为阻塞
{
perror("trying to set input socket to blocking");
return 1;
}
return 0;
}
else
{
if (errno != EINPROGRESS)
{
count_connect ++;
perror("Error: connect..2");
goto err;
}
else
{
FD_ZERO(&set);
FD_SET(socket_info.socket_descriptor_TCP, &set);
ret = select(socket_info.socket_descriptor_TCP + 1, NULL, &set, NULL, &tival);
if (ret == -1)
{
perror("Error: select");
goto err;
}
else if(ret == 0)
{
fprintf(stderr, "timeout/n");
goto err;
}
if( ret > 0)
{
if(FD_ISSET (socket_info.socket_descriptor_TCP,&set))
{
int error = 0;
socklen_t len = sizeof (error);
if(getsockopt(socket_info.socket_descriptor_TCP, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
{
printf ("Error: getsockopt fail,connected fail/n");
goto err;
}
if (error == ETIMEDOUT) {
printf ("Error: connected timeout/n");
goto err;
}
if(error == ECONNREFUSED) {
printf("Error: No one listening on the remote address./n");
goto err;
}
}
}
}
if( fcntl(socket_info.socket_descriptor_TCP, F_SETFL, savefl) == -1) //设置为阻塞
{
perror("trying to set input socket to blocking");
return 1;
}
return 0;
}
err:
printf("errno: %m /n",errno);
return 1;
}
4、UDP的recvfrom最好是非阻塞的。
原文地址:http://blog.ednchina.com/qiu1123/247360/message.aspx