Linux Socket编程 总结

在这上面花了一周多,先是思路上的致命错误,导致浪费较多时间,不过调整下很快的完成了自己所需要的代码。

期间碰到的几个比较大的问题自己做下记录:

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

你可能感兴趣的:(Linux,编程)