linux socket 释放时间 so_reuseaddr,linux網絡編程四:socket選項: SO_REUSEADDR, SO_RCVBUF, SO_SNDBUF...

最近在看《linux高性能服務器編程》,在此做個日記,以激勵自己,同時分享於有需要的朋友。

1. 讀取和設置socket文件描述符屬性:

#include

int getsockopt(int sockfd, int level, int option_name, void *option_value, socklen_t *restrict option_len);

int setsockopt(int sockfd, int level, int option_name, const void *option_value, socklen_t option_len);sockfd參數指定被操作的目標socket。

level參數指定要操作哪個協議的選項,即屬性,比如:IPv4, IPv6, TCP 和通用socket選項。

option_name參數指定選項的名字。

option_value參數指定選項的值。

option_len參參數指定選項的長度。

調用成功時返回0, 失敗時返回-1, 並設置errno。

2. 對服務器而言,有部分socket選項只能在調用listen前設置才會有效。因為連接socket只能由accept調用返回,而accept從listen監聽隊列中接受的連接至少已經完成了TCP三次握手的前兩個步聚,listen監聽隊列的連接至少已進入SYN_RCVD狀態,這時服務器已經往被連接上發送TCP同步報文。

3. SO_REUSeADDR選項:重用本地地址

未設置此項前,若服務端開啟后,又關閉,此時sock處於TIME_WAIT狀態,與之綁定的socket地址不可重用,而導致再次開啟服務端失敗。

經過setsockopt設置之后, 即使處於TIME_WAIT些狀態也可以立即被重用。

int reuse = 1;

setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizof(reuse));

4. SO_RCVBUF 和 SO_SNDBUF :TCP接收緩沖區和發送緩沖區的大小

當然,即使我們設置了這兩項的大小時, 系統都會自動將其加倍, 並且不得小於某個最小值。

TCP接收緩沖區的最小值是 256 字節, 而發送緩沖區的最小值是 2048 字節。(不同系統可能會有差異)

這么做的目的是確保一個TCP連接擁有足夠多的空閑緩沖區來處理擁塞。

setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof(sendbuf));

getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, (socklen_t*)&len);

setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof(recvbuf));

getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, (socklen_t*)&len);

5. 代碼

//服務端

#include

#include

#include

#include

#include

#include

#include

#include

#define BUFFER_SIZE 1024

int main(int argc, char **argv)

{

if (argc <= 3) {

printf("Usage: %s ip port revc_size\n", basename(argv[0]));

return 1;

}

const char *ip = argv[1];

int port = atoi(argv[2]);

struct sockaddr_in address;

bzero(&address, sizeof(address));

address.sin_family = AF_INET;

address.sin_port = htons(port);

inet_pton(AF_INET, ip, &address.sin_addr);

int sock = socket(PF_INET, SOCK_STREAM, 0);

assert(sock >= 0);

//設置地址可重用

int reuse = 1;

setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizof(reuse));

int recvbuf = atoi(argv[3]);

int len = sizeof(recvbuf);

//設置接受緩沖區大小

setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof(recvbuf));

//獲取系統修改后的大小

getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, (socklen_t*)&len);

printf("the receive buffer size after setting is %d\n", recvbuf);

int ret = bind(sock, (struct sockaddr*)&address, sizeof(address));

assert(ret != -1);

ret = listen(sock, 5);

assert(ret != -1);

struct sockaddr_in client;

socklen_t client_addrlength = sizeof(client);

int connfd = accept(sock, (struct sockaddr*)&client, &client_addrlength);

if (connfd < 0) {

printf("errno is: %d\n", errno);

}

else {

char buffer[BUFFER_SIZE];

memset(buffer, '\0', BUFFER_SIZE);

while (recv(connfd, buffer, BUFFER_SIZE-1, 0) > 0);

printf("recv: %s\n", buffer);

close(connfd);

}

close(sock);

return 0;

}

運行后:

jason@lightning:~/myproject/test_recv$ ./test_recv localhost 8000 50

the receive buffer size after setting is 2280

很明顯被修改過了, 我們給的50, 被改為2280。

//客戶端

#include

#include

#include

#include

#include

#include

#include

#define BUFFER_SIZE 1024

int main(int argc, char **argv)

{

if(argc <= 3) {

fprintf(stderr, "Usage: %s ip port send_buffer_size\n",

basename(argv[0]));

return 1;

}

const char *ip = argv[1];

int port = atoi(argv[2]);

struct sockaddr_in server_address;

bzero(&server_address, sizeof(server_address));

server_address.sin_family = AF_INET;

server_address.sin_port = htons(port);

inet_pton(AF_INET, ip, &server_address.sin_addr);

int sock = socket(PF_INET, SOCK_STREAM, 0);

assert(sock >= 0);

int sendbuf = atoi(argv[3]);

int len = sizeof(sendbuf);

//設置發送緩沖區大小

setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof(sendbuf));

//獲取系統修改后的大小

getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, (socklen_t*)&len);

printf("the tcp send buffer size after setting is %d\n",

sendbuf);

if (connect(sock, (struct sockaddr*)&server_address, sizeof(server_address)) != -1) {

char buffer[BUFFER_SIZE];

memset(buffer, 'a', BUFFER_SIZE);

send(sock, buffer, BUFFER_SIZE, 0);

}

else {

printf("connect %s failed\n", ip);

}

close(sock);

return 0;

}

運行后:

jason@lightning:~/myproject/test_send$ ./test_send localhost 8000 2000

the tcp send buffer size after setting is 4000

給的是2000, 被改成4000了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值