一次select一个socket的测试结果

硬件:刀片2

接收端代码: 1024个socketl建立连接后,创建8个线程接收数据,每个接收线程处理128个socket, 每个接收线程对每个socket先select, 再recv(2048字节)300次。

发送端代码:4个发送端,每个发送端256个线程发送数据,一共1024个socket.

加了select后, 性能和不加select直接recv比起来变化很小。但是加了select后,接收端和发送端程序不再因为阻塞时间超时而出错。程序运行的稳定性增加了。

脚本 bw.sh 统计接收端的带宽为15.78 Gb/s。

接收端的接收队列长度为2MB左右。接收端接收速度还是慢, 不过相比每个select多个socket的工作模式,接收速度已经提高了很多。

发送端代码: server1bak.c ,和上一篇博客一样

统计带宽代码:bw.sh 和上一篇一样

接收端代码: client1_multi_select.c

 1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 #include<pthread.h>
  5 #include <unistd.h>
  6 #include <time.h>
  7 
  8 #include<sys/ioctl.h>
  9 #include <sys/socket.h>
 10 #include <arpa/inet.h>
 11 #include <netinet/in.h>
 12 #include<sys/time.h>
 13 #include<string>
 14 
 15 #define PORT 33333
 16 
 17 #define SOCKNUM 1024
 18 #define THREAD_NUM 8
 19 #define SOCKET_PER_THREAD 128
 20 #define SERVER_NUM 4
 21 #define MSGSIZE 2048
 22 
 23 typedef struct{
 24     int sock[SOCKET_PER_THREAD];
 25 }ARG;
 26 
 27 int SetSocketOptions(int fd)
 28 {
 29     int sockopt = 0;
 30     int SOCKET_ERROR = -1;
31     static const int c_so_rcvbuf = 256*1024;
 32     static const int c_so_sndbuf = 256*1024;
 33 
 34     sockopt = 1;
 35     if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&sockopt, sizeof(sockopt)) == SOCKET_ERROR )
 36     {
 37         perror("set reuseaddr error");
 38         return -1;
 39     }
 40 
 41     sockopt = c_so_sndbuf;
 42     if ( setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&sockopt, sizeof(sockopt)) == SOCKET_ERROR )
 43     {
 44         perror("set so_sndbuf error");
 45         return -1;
 46     }
 47 
 48     sockopt = c_so_rcvbuf;
 49     if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&sockopt, sizeof(sockopt)) == SOCKET_ERROR )
 50     {
 51         perror("set so_rcvbuf error");
 52         return -1;
 53     }
 54 }
 55 
 56 
 57 int poll(int socket)
 58 {
 59     fd_set recv_fds;
 60     struct timeval c_select_timeout = {0, 0};
61     FD_ZERO(&recv_fds);
 62     FD_SET(socket, &recv_fds);
 63 
 64     int sel = select(socket+1, &recv_fds, NULL, NULL, &c_select_timeout);
 65     if(sel == 0)
 66     {
 67         return 0;
 68     }
 69     else if(sel > 0)
 70     {
 71         if( FD_ISSET(socket, &recv_fds) ) // socket is readable
 72         {
 73             int length;
 74             int status = ioctl(socket, FIONREAD, &length);
 75             if(status == -1)
 76             {
 77                 printf("Error reading input size
");
 78             }
 79             if(length)
 80             {
 81                 //printf("data length in socket buffer: %lf MB
", length/1024.0/1024.0);
 82                 return 1;
 83             }
 84             else
 85             {
 86                 printf("Nothing to read, eof??
");
 87                 if(socket != -1)
 88                 {
 89                     close(socket);
 90                     socket = -1;
 91                 }
 92                 perror("socket flagged but no data available probable EOF");
 93                 return 0;
 94             }
 95 
 96         }
 97         else
 98         {
 99             if(socket != -1)
100             {
101                 close(socket);
102                 socket = -1;
103             }
104             perror("FD_ISSET == zero");
105         }
106 
107     }
108     else
109     {
110         if(socket != -1)
111         {
112             close(socket);
113             socket = -1;
114         }
115         perror("select<0 error");
116     }
117 }
118 
119 
120 
121 int recvdata(int sock, char *buffer)
122 {
123     int msgsize = MSGSIZE;
124     int ret;
125     int nrecv=0;
126     while (nrecv < msgsize)
127     {
128         ret = recv(sock, buffer, msgsize-nrecv, 0);
129         if (ret < 0)
130         {
131             perror("recv fail");
132             exit(1);
133         }
134         else
135         {
136             nrecv += ret;
137         }
138     }
139     return nrecv;
140 }
141 
142 void *recvData(void *arg)
143 {
144     ARG* a = (ARG*)arg;
145     int *socket = a->sock;
146     char buffer[MSGSIZE] = "0";
147     int count = 0;
148     struct  timeval  start;
149     struct  timeval  end;
150     unsigned long timer;
151     gettimeofday(&start,NULL);
152 
153     while(1)
154     {
155         for(int i=0; i<SOCKET_PER_THREAD; i++)
156         {
157             if( poll(socket[i]) )
158             {
159             for(int num=0; num<300; num++)
160             recvdata(socket[i], buffer);
161             }
162 #if 0
163             count++;
164             gettimeofday(&end,NULL);
165             timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec;
166             if(timer % 5000000==0)
167             {
168                 printf("timer = %ld us, %lf Gb/s
",timer, count*2048.0/timer/1024*8);
169             }
170 #endif
171         }
172     }
173     return 0;
174 }
175 
176 
177 int main()
178 {
179     int sock[SERVER_NUM][SOCKNUM/SERVER_NUM];
180     struct sockaddr_in addr_ser[SERVER_NUM];
181     struct sockaddr_in addr_cli[SERVER_NUM][SOCKNUM/SERVER_NUM];
182 
183     std::string local_ip("192.168.250.141");
184 
185     std::string server_ip[SERVER_NUM] = {"192.168.250.146", "192.168.250.147", "192.168.250.142", "192.168.250.143"};
186     //std::string server_ip[SERVER_NUM] = {"192.168.251.166", "192.168.251.167", "192.168.251.162", "192.168.251.163"}; 
187 //  std::string server_ip[SERVER_NUM] = {"192.168.251.163"}; 
188     for(int ser=0; ser < SERVER_NUM; ser++)
189     {
190     for(int i=0; i<SOCKNUM/SERVER_NUM; i++)
191     {
192         sock[ser][i] = socket(AF_INET, SOCK_STREAM, 0);
193         if(sock[ser][i] < 0)
194         {
195             printf("%d ", i);
196             perror("create socket fail");
197         }
198 
199         addr_ser[ser].sin_family = AF_INET;
200         addr_ser[ser].sin_port = htons(PORT);
201         addr_ser[ser].sin_addr.s_addr = inet_addr(server_ip[ser].c_str());
202 
203         addr_cli[ser][i].sin_family = AF_INET;
204         addr_cli[ser][i].sin_port = 0;
205         addr_cli[ser][i].sin_addr.s_addr = inet_addr(local_ip.c_str());
206 
207 
208         int sockopt = 1;
209         if ( setsockopt(sock[ser][i], SOL_SOCKET, SO_REUSEADDR, (char*)&sockopt, sizeof(sockopt)) == -1 )
210         {
211             perror("set reuseaddr error");
212             exit(1);
213         }
214 
215 
216 #if 0 
217 
218         if ( SetSocketOptions(sock[ser][i]) == -1)
219         {
220             perror("set socket options error");
221             exit(1);
222         }
223 #endif
224 
225         if( bind(sock[ser][i], (struct sockaddr*)&addr_cli[ser][i], sizeof(addr_cli[ser][i]) ) < 0 )
226         {
227             perror("TCP bind: ");
228             exit(1);
229         }
230         printf("bind ok!
");
231 
232         if(connect(sock[ser][i], (struct sockaddr*)&addr_ser[ser], sizeof(struct sockaddr)) < 0)
233         {
234             perror("connect fail:");
235             exit(1);
236         }
237         printf("connect ok!
");
238 
239     }
240 
241     }
242 
243 
244     int socket[SOCKNUM] ;
245     int count=0;
246     for(int i=0; i< SERVER_NUM; i++)
247     {
248         for(int j=0; j<SOCKNUM/SERVER_NUM; j++)
249         {
250             socket[count++] = sock[i][j];
251         }
252     }
253 
254     pthread_t tid[THREAD_NUM];
255     ARG a[THREAD_NUM];
256     for(int i=0; i<THREAD_NUM; i++)
257     {
258         for(int j=0; j<SOCKET_PER_THREAD; j++)
259         {
260         a[i].sock[j] = socket[i*SOCKET_PER_THREAD+j];
261         }
262         pthread_create(&tid[i], 0, recvData, (void *)&a[i]);
263     }
264 
265     for(int i=0; i<SOCKNUM; i++)
266     {
267         pthread_join(tid[i], 0);
268     }
269 
270     return 0;
271 }
原文地址:https://www.cnblogs.com/zengtx/p/6796193.html