套接字的多种可选项

套接字可选项和I/O缓冲大小 

套接字多种可选项

  我们之前写的程序都是创建好套接字后(未经特别操作)直接使用的,此时通过默认的套接字特性进行数据通信,有时需要对套接字的特性进行更改。

 

套接字可选项是分层的,IPPROTO_IP层可选项是IP协议相关事项,IPPROTO_TCP层可选项是TCP协议相关的事项,SOL_SOCKET层是套接字相关的通用可选项。 

可选项的读取和设置

 通过getsockopt函数读取可选项

通过setsockopt函数设置可选项

 

 

示例

 查看缓冲区的大小

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
void error_handling(char *message);

int main(int argc, char *argv[])
{
	int sock;
	int snd_buf, rcv_buf, state;
	socklen_t len;

	sock=socket(PF_INET, SOCK_STREAM, 0);
	len=sizeof(snd_buf);
	state=getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, &len);
	if(state)
		error_handling("getsockopt() error");

	len=sizeof(rcv_buf);
	state=getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, &len);
	if(state)
		error_handling("getsockopt() error");

	printf("Input buffer size: %d \n", rcv_buf);
	printf("Outupt buffer size: %d \n", snd_buf);
	return 0;
}

void error_handling(char *message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

 

设置缓冲区的大小

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
void error_handling(char *message);

int main(int argc, char *argv[])
{
	int sock;
	int snd_buf=1024*3, rcv_buf=1024*3;
	int state;
	socklen_t len;
	
	sock=socket(PF_INET, SOCK_STREAM, 0);
	state=setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, sizeof(rcv_buf));
	if(state)
		error_handling("setsockopt() error!");
	
	state=setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, sizeof(snd_buf));
	if(state)
		error_handling("setsockopt() error!");
	
	len=sizeof(snd_buf);
	state=getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, &len);
	if(state)
		error_handling("getsockopt() error!");
	
	len=sizeof(rcv_buf);
	state=getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, &len);
	if(state)
		error_handling("getsockopt() error!");
	
	printf("Input buffer size: %d \n", rcv_buf);
	printf("Output buffer size: %d \n", snd_buf);
	return 0;
}

void error_handling(char *message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

 输出结果和我们设置的不同,具体原因可以参考这篇文章Socket缓冲区大小修改与系统设置_mfence的博客-CSDN博客_socket缓冲区大小设置

SO_REUSEADDR

  在之前的回声客户端与服务器端的程序中,客户端先请求断开连接,重新运行服务器端也不会有什么问题;但如果在客户端与服务器端已建立连接的状态下,向服务器端控制台输入(CTRL+C),即强制关闭服务器端,那么使用同一端口号重新运行服务器端时,将输出"bind() error"消息,无法再次运行,再过大约3分钟可重新运行服务器端。

Time-wait状态

  套接字经过四次挥手过程后并非立即消除,而是要经过一段时间的Time-wait状态。只有先断开连接的(先发送FIN消息的)主机才经过Time-wait状态,套接字处在Time-wait过程时,相应端口是正在使用的状态。无需考虑客户端Time-wait状态,因为客户端套接字的端口号是任意指定的。 

为何要有Time-wait状态

  在图9-1中,如果主机A向主机B发送的ACK信息丢失,如果没有Time-wait状态,主机B将重传FIN信息,但主机B永远收不到回信。

地址再分配

   四次挥手过程中,如果最后的数据丢失,主机B会认为主机A未能收到自己发送的FIN消息,因此重传。收到FIN消息的主机A将重启Time-wait计时器。如果网络状态不理想,Time-wait状态将持续。

  SO_REUSEADDR状态:是否启用地址再分配,主要原理是操作关闭套接字的Time-wait时间等待的开启和关闭。SO_REUSEADDR的默认值为0(假),将这个值改成1(真),可将Time-wait状态下的套接字端口号重新分配给新的套接字。

TCP_NODELAY

Nagle算法

 只有收到前一数据的ACK消息时,Nagle算法才发送下一数据。

  未准确判断数据特性时不应禁用Nagle算法 。

禁用Nagle算法

将TCP_NODELAY改为1(真)即可禁用Nagle算法:

int opt_val=1;
setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(void *)&opt_val,sizeof(opt_val));

查看Nagle算法的设置状态:

int opt_val;
socklen_t opt_len;
opt_len=sizeof(opt_val);
getsockopt(sock,IPPROTO_TCP, TCP_NODELAY,(void*) &opt_val, &opt_len);
如果正在使用 Nagle 算法, opt _ val 变量 会保存 0; 如果已禁用 Nagle 算法, 则保存1。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值