/[LeafOK_CVS]/lbbs/src/tcplib.c
ViewVC logotype

Diff of /lbbs/src/tcplib.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.2 by sysadm, Mon Apr 28 03:31:00 2025 UTC Revision 1.5 by sysadm, Sat May 10 05:33:22 2025 UTC
# Line 1  Line 1 
1  #include "tcplib.h"  #include "tcplib.h"
2    #include "common.h"
 void MsToTimeval(const int ms, struct timeval *tv)  
 {  
         tv->tv_sec = ms / TIME_CNV_RATIO;  
         tv->tv_usec = (ms - tv->tv_sec * TIME_CNV_RATIO) * TIME_CNV_RATIO;  
 }  
   
 int TimevalToMs(const struct timeval *tv)  
 {  
         return (tv->tv_sec * TIME_CNV_RATIO + tv->tv_usec / TIME_CNV_RATIO);  
 }  
   
 void TimevalSubtract(struct timeval *ltv, const struct timeval *rtv)  
 {  
         if (ltv->tv_usec < rtv->tv_usec)  
         {  
                 ltv->tv_sec--;  
                 ltv->tv_usec += TIME_CNV_RATIO * TIME_CNV_RATIO;  
         }  
         ltv->tv_sec -= rtv->tv_sec;  
         ltv->tv_usec -= rtv->tv_usec;  
 }  
   
 int NonBlockConnect(int sockfd, const struct sockaddr *saptr, socklen_t salen,  
                                         const int msec)  
 {  
         int flags, n, error;  
         socklen_t len;  
         fd_set rset, wset;  
         struct timeval tval;  
   
         /*  
          * 设置为非阻塞的 socket  
          */  
         flags = fcntl(sockfd, F_GETFL, 0);  
         fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);  
   
         error = 0;  
         if ((n = connect(sockfd, saptr, salen)) < 0)  
         {  
                 if (errno != EINPROGRESS)  
                         return ERR_TCPLIB_CONNECT; /* 连接失败 */  
         }  
   
         /*  
          * Do whatever we want while the connect is taking place.  
          */  
   
         if (n == 0)  
                 goto done; /* connect completed immediately */  
   
         FD_ZERO(&rset);  
         FD_SET(sockfd, &rset);  
         wset = rset; /* structure assignment */  
         MsToTimeval(msec, &tval);  
   
         n = SignalSafeSelect(sockfd + 1, &rset, &wset, NULL, msec ? &tval : NULL);  
         if (n == 0)  
         {  
                 errno = ETIMEDOUT;  
                 return ERR_TCPLIB_TIMEOUT; /* 连接服务器超时 */  
         }  
         else if (n < 0)  
                 return ERR_TCPLIB_OTHERS; /* select()出错 */  
         if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset))  
         {  
                 len = sizeof(error);  
                 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)  
                         return ERR_TCPLIB_OTHERS; /* Solaris pending error */  
         }  
   
 done:  
         fcntl(sockfd, F_SETFL, flags); /* restore file status flags */  
   
         if (error)  
         {  
                 errno = error;  
                 return ERR_TCPLIB_CONNECT; /* 连接服务器失败 */  
         }  
         return 0; /* 连接服务器成功 */  
 }  
3    
4  int NonBlockConnectEx(int sockfd, const struct sockaddr *saptr, socklen_t salen,  int NonBlockConnectEx(int sockfd, const struct sockaddr *saptr, socklen_t salen,
5                                            const int msec, const int conn)                                            const int msec, const int conn)
6  {  {
7          int flags, n, error;          int flags, ret, error;
8          socklen_t len;          socklen_t len;
9          fd_set rset, wset;          fd_set rset, wset;
10          struct timeval tval;          struct timeval tval;
# Line 98  int NonBlockConnectEx(int sockfd, const Line 18  int NonBlockConnectEx(int sockfd, const
18          error = 0;          error = 0;
19          if (conn == 1)          if (conn == 1)
20          {          {
21                  if ((n = connect(sockfd, saptr, salen)) < 0)                  if ((ret = connect(sockfd, saptr, salen)) < 0)
22                  {                  {
23                          if (errno != EINPROGRESS)                          if (errno != EINPROGRESS)
24                            {
25                                  return ERR_TCPLIB_CONNECT; /* 连接失败 */                                  return ERR_TCPLIB_CONNECT; /* 连接失败 */
26                            }
27                  }                  }
28    
29                  /*                  /*
30                   * Do whatever we want while the connect is taking place.                   * Do whatever we want while the connect is taking place.
31                   */                   */
32                    if (ret == 0)
33                  if (n == 0)                  {
34                          goto done; /* connect completed immediately */                          goto done; /* connect completed immediately */
35                    }
36          }          }
37    
38          FD_ZERO(&rset);          tval.tv_sec = msec / 1000;
39          FD_SET(sockfd, &rset);          tval.tv_usec = msec % 1000 * 1000;
         wset = rset; /* structure assignment */  
         MsToTimeval(msec, &tval);  
   
         n = SignalSafeSelect(sockfd + 1, &rset, &wset, NULL, msec ? &tval : NULL);  
         if (n == 0)  
         {  
                 errno = ETIMEDOUT;  
                 return ERR_TCPLIB_TIMEOUT; /* 连接服务器超时 */  
         }  
         else if (n < 0)  
                 return ERR_TCPLIB_OTHERS; /* select()出错 */  
         if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset))  
         {  
                 len = sizeof(error);  
                 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)  
                         return ERR_TCPLIB_OTHERS; /* Solaris pending error */  
         }  
   
 done:  
         fcntl(sockfd, F_SETFL, flags); /* restore file status flags */  
   
         if (error)  
         {  
                 errno = error;  
                 return ERR_TCPLIB_CONNECT; /* 连接服务器失败 */  
         }  
         return 0; /* 连接服务器成功 */  
 }  
   
 int DoConnect(const char *ip, const int port, const int msec)  
 {  
         struct sockaddr_in sa;  
         int conn_fd;  
         int rv;  
   
         /*  
          * assert(ip != NULL && port != 0);  
          */  
40    
41          /*          while (!SYS_server_exit)
          * 创建 socket  
          */  
         if ((conn_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)  
                 return ERR_TCPLIB_OTHERS; /* 创建 socket 失败 */  
         /*  
          * 设置 sockaddr_in 结构  
          */  
         bzero(&sa, sizeof(sa));  
         sa.sin_family = AF_INET;  
 #ifdef HAVE_INET_ATON  
         if (inet_aton(ip, &sa.sin_addr) <= 0)  
 #else  
         if (inet_pton(AF_INET, ip, &sa.sin_addr) <= 0)  
 #endif  
                 return ERR_TCPLIB_OTHERS; /* 获取服务器地址失败 */  
         sa.sin_port = htons(port);  
         /*  
          * 创建连接  
          */  
         rv = NonBlockConnect(conn_fd, (struct sockaddr *)&sa, sizeof(sa), msec);  
         if (rv < 0)  
42          {          {
43                  /*                  FD_ZERO(&rset);
44                   * 创建连接失败,关掉 socket                  FD_SET(sockfd, &rset);
                  */  
                 close(conn_fd);  
                 return rv;  
         }  
45    
46          return conn_fd;                  FD_ZERO(&wset);
47  }                  FD_SET(sockfd, &wset);
48    
49  void DoDisconnect(int conn_fd)                  ret = select(sockfd + 1, &rset, &wset, NULL, &tval);
 {  
         close(conn_fd);  
 }  
   
 int SignalSafeSelect(int nfds, fd_set *rs, fd_set *ws, fd_set *es,  
                                          struct timeval *tv)  
 {  
         int rv;  
50    
51          while ((rv = select(nfds, rs, ws, es, tv)) < 0)                  if (ret == 0)
52          {                  {
53                  if (errno != EINTR)                          return ERR_TCPLIB_TIMEOUT; /* 连接服务器超时 */
54                          break;                  }
55          }                  else if (ret < 0)
56          return rv;                  {
57  }                          if (errno != EINTR)
58                            {
59                                    return ERR_TCPLIB_OTHERS; /* select()出错 */
60                            }
61                            continue;
62                    }
63    
64  int SafeAccept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)                  if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset))
 {  
         int flags, n;  
         fd_set rset;  
         int conn_fd = ERR_TCPLIB_OTHERS;  
   
         FD_ZERO(&rset);  
         FD_SET(sockfd, &rset);  
         n = SignalSafeSelect(sockfd + 1, &rset, NULL, NULL, NULL);  
         if (n < 0)  
                 return ERR_TCPLIB_OTHERS;  
         if (FD_ISSET(sockfd, &rset))  
         {  
                 /*  
                  * 设置为非阻塞的 socket  
                  */  
                 flags = fcntl(sockfd, F_GETFL, 0);  
                 fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);  
                 /*  
                  * 然后调用 accept() 接受连接请求  
                  */  
                 while ((conn_fd = accept(sockfd, cliaddr, addrlen)) < 0)  
65                  {                  {
66                          /*                          len = sizeof(error);
67                           * from UNPv1 Page 424                          if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
68                           */                          {
69                          if (errno != EWOULDBLOCK && errno != ECONNABORTED && errno != EINTR)                                  return ERR_TCPLIB_OTHERS; /* Solaris pending error */
70                                  break;                          }
71                  }                  }
                 /*  
                  * 使 socket 复原  
                  */  
                 fcntl(sockfd, F_SETFL, flags);  
         }  
         return conn_fd;  
 }  
72    
73  int DoSendData(int sockfd, const void *buf, const size_t len, int msec)                  break;
 {  
         struct timeval tv;  
         fd_set wset;  
         int rv;  
         int wc;  
   
         MsToTimeval(msec, &tv);  
         FD_ZERO(&wset);  
         FD_SET(sockfd, &wset);  
         rv = SignalSafeSelect(sockfd + 1, NULL, &wset, NULL, &tv);  
         if (rv < 0)  
                 return ERR_TCPLIB_OTHERS; /* some error occured */  
         if (rv == 0)  
                 return ERR_TCPLIB_TIMEOUT; /* timed out */  
         if (FD_ISSET(sockfd, &wset))  
         {  
                 /*  
                  * 一次发送所有数据  
                  */  
                 wc = send(sockfd, buf, len, 0);  
                 return wc; /* return bytes had sent */  
74          }          }
         return 0; /* nothing had sent */  
 }  
75    
76  int DoRecvData(int sockfd, void *buf, const size_t len, int msec)  done:
77  {          fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
78          struct timeval tv;  
79          fd_set rset;          if (error)
         int rv;  
         int rc;  
   
         MsToTimeval(msec, &tv);  
         FD_ZERO(&rset);  
         FD_SET(sockfd, &rset);  
         rv = SignalSafeSelect(sockfd + 1, &rset, NULL, NULL, msec ? &tv : NULL);  
         if (rv < 0)  
                 return ERR_TCPLIB_OTHERS; /* some error occured */  
         if (rv == 0)  
                 return ERR_TCPLIB_TIMEOUT; /* timed out */  
         if (FD_ISSET(sockfd, &rset))  
80          {          {
81                  /*                  errno = error;
82                   * 一次接收所有数据                  return ERR_TCPLIB_CONNECT; /* 连接服务器失败 */
                  */  
                 rc = recv(sockfd, buf, len, 0);  
                 return rc; /* return bytes had received */  
83          }          }
84          return 0; /* nothing had received */  
85            return 0; /* 连接服务器成功 */
86  }  }


Legend:
Removed lines/characters  
Changed lines/characters
  Added lines/characters

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1