socket開發總結

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
相關文章
相關標籤/搜索