企业级TCP处理要点-网络IO

1 网络IO编程要点

1.1 连接建立

服务器接收客户端连接:

  • 注意三次握手时机,服务器在接收客户端返回ack才是加入到全连接队列;
  • accpet函数将全连接队列数据拷贝到用户区。
//backlog为全连接队列的大小
listen(sockfd, backlog);
int clientfd = accept(listenfd, &addr, &size);

客户端连接服务器:

  • 客户端连接服务器成功需要客户端发送ack成功才能成功
int connectfd = socket(AF_INET, SOCK_STREAM, 0);
connect(connectfd, (struct sockaddr *)&addr, sizeof(addr));

1.2 连接断开

主动断开:

  • 主动断开分为三种模式,关闭读写端,关闭读端,关闭写端
//关闭读写端
close(fd);
shutdown(SHUT_RDWR);
//关闭读端
shutdown(SHUT_RD);
//关闭写端
shutdown(SHUT_WR);

被动断开:

  • 对于需要进行半连接操作的,可以利用读端或者写端关闭;操作对于的写端和读端
  • read返回值为0 为读端被动关闭;
  • write返回值为-1 同时errno数值为EPIPE为写端被动关闭;
//接收端读端被动关闭;发送端写端关闭。
int n = read(fd, buf, size);
if (n == 0) {
	read_close(fd);//可以进行写相关操作,之后close(fd);
}
//被动写端关闭
int n = write(fd, buf, size);
if (n == -1 && errno == EPIPE) {
	write_close(fd);//可以进行读相关操作,之后close(fd);
}

1.3 数据到达

  • 消息到达需要忽略EINTR系统中断错误;
  • 消息到达需要忽略EWOULDBLOCK接收缓冲区为空的错误,当没有数据需要退出循环读数据;
  • 其他错误需要:调用close关闭连接
while(1)
{
	int n = read(fd, buf, size);
	if (n < 0) { // n == -1
		if (errno == EINTR || errno == EWOULDBLOCK)
			break;
		close(fd);
	} else if (n == 0) {
		close(fd);
	} else {
		// 处理接收数据
	}
}

1.4 数据发送完毕

  • EINTR系统中断直接返回;等待下一次触发写;
  • EWOULDBLOCK写缓冲区满返回;等待下一次写;
  • 其他错误关闭连接;
  • 注意写的大小一定是等于size的大小,当不等于的情况一般是返回失败的。
int n = write(fd, buf, size);
if (n == -1) {
	if (errno == EINTR || errno == EWOULDBLOCK) {
		return;
	}
	close(fd);
}

1.5 非阻塞IO

  • 阻塞非阻塞其实是阻塞在网络线程
  • 只需要对socketfd设置非阻塞属性既可以保证IO函数是非阻塞的
  • 阻塞与非阻塞差异:IO函数在数据未到达是否立即返回
// 默认情况下,fd 是阻塞的,设置非阻塞利用fcntl;
int flag = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flag | O_NONBLOCK);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值