1.connect併發
阻塞socket connect時會等待返回結果,等於0表示成功,小於0表示失敗。socket
非阻塞socket connect時會馬上返回結果,等於0表示成功,小於0且errno == EINPROGRESS時表示鏈接正在進行,此時應該等待該socket觸發寫信號,觸發時獲取該socket的SO_ERROR選項,根據此值來判斷socket是否connect成功。tcp
2.send函數
[1]返回值等於發送長度,則表示成功。spa
[2]返回值小於發送長度,可是大於0,則表示發送緩衝區已滿,等待繼續發送剩下的數據。code
[3]返回值小於0,若是(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK || errno == 0)這些狀況時,表示須要再次嘗試發送。server
[4]返回值等於0,表示傳入的長度參數就是0或者緩衝區已滿,應該嘗試繼續發送。blog
阻塞和非阻塞的處理方式是同樣的,只有返回值小於0時,才能判斷errno的值,不然errno的值是無效的。進程
若是send時,當前socket已經斷開(對方已經關閉),此時底層會拋出一個SIGPIPE信號,這個信號的缺省處理方法是退出進程,因此須要設置忽略此信號。事件
3.recv
[1]返回值大於0表示接收成功。
[2]返回值小於0時,若是(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK || errno == 0)這些狀況時,表示須要再次嘗試接收。
[3]返回值等於0時,表示鏈接斷開,須要關閉socket。
阻塞和非阻塞的處理方式是同樣的,只有返回值小於0時,才能判斷errno的值,不然errno的值是無效的。
4.accept
accept以後會返回一個新的socket,注意要看狀況給這個socket設置相關的選項。
5.select、epoll
[1]select(maxfd + 1, &rfd, &wfd, NULL, &timeout);
最後一個參數是超時時間,若是傳0(struct timeval timeout = {0,0})表示只遍歷一遍就返回。若是傳NULL,表示直到遍歷到有事件才返回。若是傳大於0的值,則表示超時時間。
[2]epoll_wait(fd, events_ready, max_fd, -1);
LT模式:socket有事件時通知應用程序,例若有讀事件時:此時能夠read緩衝區的部分或者所有數據(直到返回-1,errno爲EAGAIN),也能夠不作任何處理,由於下次epoll_wait時,若是緩衝區有數據還會再次觸發信號。
ET模式:socket有事件時通知應用程序,可是隻會通知一次,直到應用程序作了操做致使下次狀態改變時纔會再次觸發,例若有讀事件時:必須把緩衝區數據讀完。這個模式只支持非阻塞socket。
缺省是LT模式,若是要使用ET模式,則添加事件時加上EPOLLET標記:event.events = EPOLLIN | EPOLLOUT | EPOLLET;
注意select和epoll的最後一個值是超時時間,若是這個函數後面還有其餘流程處理(例如檢查狀態等),則必定要設置一個固定的超時時間或者填0。
6.socket相關操做
/*設置文件打開數*/ struct rlimit l; l.rlim_cur = 90000; l.rlim_max = 90000; setrlimit(RLIMIT_NOFILE, &l); /*忽略SIGPIPE信號,不然對端關閉socket時,本端調用send()函數會致使進程退出*/ signal(SIGPIPE, SIG_IGN); /*connect觸發寫信號時,經過判斷該值判斷鏈接是否成功。*/ int cc, optlen = sizeof(cc); getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&cc, (void *)&optlen); /*設置socket的發送、接收緩衝區*/ int size = 8 * 1024 *1024; setsockopt(sk, SOL_SOCKET, SO_SNDBUF, (void *)&size, sizeof(size)); setsockopt(sk, SOL_SOCKET, SO_RCVBUF, (void *)&size, sizeof(size)); /*阻塞socket設置收發超時時間*/ struct timeval tv = {2,0}; setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval)); setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); /*獲取tcp socket的目的地址*/ struct sockaddr_in server_addr; getsockname(fd, (struct sockaddr *)&server_addr, &addrlen);
7.內核相關參數
//設置socket的發送、接收緩衝區最大值 sysctl -w net.core.rmem_max=104857600 sysctl -w net.core.wmem_max=104857600 //設置能夠綁定的端口範圍,多併發時使用 echo 1024 65535 >/proc/sys/net/ipv4/ip_local_port_range //設置快速回收TIME_WAIT鏈接 sysctl net.ipv4.tcp_tw_recycle=1