1024个读出线程的测试结果
1024个读出线程,发送端不控制速度。测试包长2KB, 测试时间983秒时, 单个线程的带宽为0.0068Gb/s, 此时的拥塞窗口为17,rtt为45000. 发送端的cpu占用率为18%, 接收端的CPU占用率为34%。接收端的Recv-Q为0,发送端的Send-Q为几百KB。
发送端和接收端先建立1024个连接,然后再用pthread_create创建1024个线程,发送端每个线程调用send()函数发送数据,接收端每个线程调用recv()函数接收数据。
在发送数据的初期,单线程的带宽达到200Mb/s,随着每个线程发送到网络的分组越来越多,网络发生了拥塞,tcp的重传率明显提高到2%, 接着拥塞窗口不断降低,带宽也降低到一个很小的值,接着会发生慢启动的过程,带宽又逐渐上升,并维持在每个线程6Mb/s左右, 总带宽大约为6Gb/s左右。
测试程序:
服务器端:g++ -lpthread server1bak.c -o sbak
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #include<pthread.h> 5 #include <unistd.h> 6 7 #include <sys/socket.h> 8 #include <arpa/inet.h> 9 #include <netinet/in.h> 10 #include <netinet/tcp.h> 11 #include<sys/time.h> 12 #include<errno.h> 13 #include<string.h> 14 15 #define IP "192.168.250.146" 16 #define PORT 33333 17 #define SOCKNUM 1024 18 #define PACKETSIZE 2048 19 20 typedef struct { 21 int sock; 22 }ARG; 23 24 pthread_t tid[SOCKNUM]; 25 26 int senddata(int sock) 27 { 28 int ret; 29 char temp[PACKETSIZE+1] = "I want to know!"; 30 int size_left=2048; 31 while( size_left > 0) 32 { 33 ret = send(sock, temp, size_left, 0); 34 if (ret < 0) 35 { 36 perror("send fail"); 37 exit(1); 38 } 39 size_left -= ret; 40 } 41 42 return size_left; 43 } 44 45 46 int read_cwnd(int tcp_work_socket) 47 { 48 struct tcp_info info; 49 socklen_t tcp_info_length = sizeof(tcp_info); 50 if ( getsockopt(tcp_work_socket, SOL_TCP, TCP_INFO, (void *)&info, &tcp_info_length) == 0 ) { 51 printf(" cwnd:%u, snd_ssthresh:%u, rtt:%u, rtt_d:%u\n", 52 info.tcpi_snd_cwnd, 53 info.tcpi_snd_ssthresh, 54 info.tcpi_rtt, 55 info.tcpi_rttvar 56 ); 57 } 58 return 0; 59 } 60 61 62 void *sendData(void *arg) 63 { 64 #if 1 65 ARG *a = (ARG *)arg; 66 int accept_sock = a->sock; 67 68 long count = 0; 69 struct timeval start; 70 struct timeval end; 71 unsigned long timer=0; 72 gettimeofday(&start,NULL); 73 74 75 while(1){ 76 senddata(accept_sock); 77 //usleep(850); 78 if(pthread_self()== tid[0]) 79 { 80 // FILE* fpointer = fopen("result.out", "a+"); 81 count++; 82 gettimeofday(&end,NULL); 83 timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; 84 if(timer%1000== 0) 85 { 86 printf("count: %ld, socket: %ld, %lf s, %lf Gb/s, ", count, accept_sock, timer/1000000.0, count*2048.0/timer/1024*8); 87 read_cwnd(accept_sock); 88 } 89 90 #if 1 91 if(timer > 3600000000) 92 { 93 printf("before close: timer: %ld\n", timer); 94 close(accept_sock); 95 // fclose(fpointer); 96 break; 97 } 98 #endif 99 } 100 } 101 return 0; 102 #endif 103 104 } 105 106 107 108 int main() 109 { 110 int accept_sock[SOCKNUM]; 111 struct sockaddr_in addr_ser; 112 113 114 int sock = socket(AF_INET, SOCK_STREAM, 0); 115 if (sock < 0) 116 { 117 perror("create sock fail"); 118 exit(1); 119 } 120 121 addr_ser.sin_family = AF_INET; 122 addr_ser.sin_port = htons(PORT); 123 addr_ser.sin_addr.s_addr = inet_addr(IP); 124 125 126 int sockopt = 1; 127 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char *)&sockopt, sizeof(int)) < 0) 128 { 129 perror("setsockopt fail"); 130 exit(1); 131 } 132 133 if (bind(sock, (struct sockaddr*)&addr_ser, sizeof(struct sockaddr)) < 0) 134 { 135 perror("bind fail"); 136 exit(1); 137 } 138 139 if (listen(sock, 2000) < 0) 140 { 141 perror("listen fail"); 142 exit(1); 143 } 144 145 146 for(int i=0; i<SOCKNUM; i++) 147 { 148 149 accept_sock[i] = accept(sock, 0, 0); 150 if (accept_sock[i] < 0) 151 { 152 perror("accept fail"); 153 exit(1); 154 } 155 printf("accept ok!\n"); 156 } 157 158 159 #if 1 160 161 //static extern pthread_t tid[SOCKNUM]; 162 ARG a[SOCKNUM]; 163 for(int i=0; i<SOCKNUM; i++){ 164 a[i].sock = accept_sock[i]; 165 pthread_create(&tid[i], 0, sendData, (void *)&a[i]); 166 } 167 #endif 168 169 #if 1 170 for(int i=0; i<SOCKNUM; i++) 171 { 172 pthread_join(tid[i], 0); 173 } 174 #endif 175 176 return 0; 177 }
客户端: g++ -lpthread client1_multi_sock.c -o cbak
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/socket.h> 9 #include <arpa/inet.h> 10 #include <netinet/in.h> 11 #include<sys/time.h> 12 #include<string> 13 14 #define IP "192.168.250.146" 15 #define PORT 33333 16 17 #define SOCKNUM 1024 18 #define THREAD_NUM 1024 19 #define SOCKET_PER_THREAD 1 20 21 22 typedef struct{ 23 int sock[SOCKET_PER_THREAD]; 24 }ARG; 25 26 27 int recvdata(int sock, char *buffer) 28 { 29 int msgsize = 2048; 30 int ret; 31 int nrecv=0; 32 while (nrecv < msgsize) 33 { 34 ret = recv(sock, buffer, msgsize-nrecv, 0); 35 if (ret < 0) 36 { 37 perror("recv fail"); 38 exit(1); 39 } 40 else 41 { 42 nrecv += ret; 43 } 44 } 45 return nrecv; 46 } 47 48 void *recvData(void *arg) 49 { 50 ARG* a = (ARG*)arg; 51 int *socket = a->sock; 52 char buffer[2048] = "0"; 53 int count = 0; 54 struct timeval start; 55 struct timeval end; 56 unsigned long timer; 57 gettimeofday(&start,NULL); 58 59 while(1) 60 { 61 for(int i=0; i<SOCKET_PER_THREAD; i++) 62 { 63 recvdata(socket[i], buffer); 64 #if 0 65 count++; 66 gettimeofday(&end,NULL); 67 timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; 68 if(timer % 5000000==0) 69 { 70 printf("timer = %ld us, %lf Gb/s\n",timer, count*2048.0/timer/1024*8); 71 } 72 #endif 73 } 74 } 75 return 0; 76 } 77 78 79 int main() 80 { 81 int sock[SOCKNUM]; 82 int port[SOCKNUM]; 83 struct sockaddr_in addr_ser; 84 struct sockaddr_in addr_cli[SOCKNUM]; 85 86 std::string local_ip("192.168.250.141"); 87 88 for(int i=0; i<SOCKNUM; i++) 89 { 90 sock[i] = socket(AF_INET, SOCK_STREAM, 0); 91 if(sock[i] < 0) 92 { 93 printf("%d ", i); 94 perror("create socket fail"); 95 } 96 97 addr_ser.sin_family = AF_INET; 98 addr_ser.sin_port = htons(PORT); 99 addr_ser.sin_addr.s_addr = inet_addr(IP); 100 101 addr_cli[i].sin_family = AF_INET; 102 addr_cli[i].sin_port = htons(12345+i); 103 addr_cli[i].sin_addr.s_addr = inet_addr(local_ip.c_str()); 104 105 106 107 int sockopt = 1; 108 if (setsockopt(sock[i], SOL_SOCKET, SO_REUSEADDR, (char*)&sockopt, sizeof(sockopt)) == -1) 109 { 110 perror("set reuse fail "); 111 exit(1); 112 } 113 114 if( bind(sock[i], (struct sockaddr*)&addr_cli[i], sizeof(addr_cli[i]) ) < 0 ) 115 { 116 perror("TCP bind: "); 117 exit(1); 118 } 119 printf("bind ok!\n"); 120 121 if(connect(sock[i], (struct sockaddr*)&addr_ser, sizeof(struct sockaddr)) < 0) 122 { 123 perror("connect fail:"); 124 exit(1); 125 } 126 printf("connect ok!\n"); 127 128 } 129 130 131 pthread_t tid[THREAD_NUM]; 132 ARG a[THREAD_NUM]; 133 for(int i=0; i<THREAD_NUM; i++) 134 { 135 for(int j=0; j<SOCKET_PER_THREAD; j++) 136 { 137 a[i].sock[j] = sock[i*SOCKET_PER_THREAD+j]; 138 } 139 pthread_create(&tid[i], 0, recvData, (void *)&a[i]); 140 } 141 142 for(int i=0; i<SOCKNUM; i++) 143 { 144 pthread_join(tid[i], 0); 145 } 146 147 return 0; 148 }