笔记-9-30

服务端测试

01-server.c 02-client.c
编译
gcc -o server 01-server.c
运行
./server
堵塞在accept
新的终端测试工具
nc 127.1 8888
输入

客户端测试
编译
gcc -o client 02-server.c
运行
./client

测试过程中可以使用netstat命令查看监听状态和连接状态
netstat命令:
a 表示显示所有
n 表示显示的时候以数字的方式来显示
p 表示显示进程信息(进程名和进程PID)

lgw@lgw-Lenovo-XiaoXin-Air-13-Pro:~$ netstat -anp | grep 8888
(并非所有进程都能被检测到,所有非本用户的进程信息将不会显示,如果想看到所有信息,则必须切换到 root 用户)
tcp 0 0 0.0.0.0:8888 0.0.0.0:* LISTEN 2757/server
tcp 0 0 127.0.0.1:8888 127.0.0.1:43432 ESTABLISHED 2757/server
tcp 0 0 127.0.0.1:43432 127.0.0.1:8888 ESTABLISHED 2797/client

一些细节
1、调用accept函数据不是说新建一个连接,而是从已连接队列中取出一个可用连接。

函数封装思想

像accept和read这样能够引起阻塞的函数,若被信号打断,由于信号的优先级较高,会优先处理信号,信号处理完成后,会accept或者read解除阻塞,然后返回,此时返回值为-1,设置errno=EINTR
errno=ECONNABORTED 表示连接被打断,异常了。

errno宏
在/usr/include/asm-generic/errno.h 文件中包含了errno所有的宏和对应的错误描述信息
命令 man errno 可以查看帮助文件

多进程并发服务器

解决办法1
将cfd设置为非阻塞:fcntl
假如有多个客户端连接请求,cfd只会保留最后一个文件描述符的值
解决方法2
使用多进程:让父进程监听接收新的连接,子进程处理新的连接(接收和发送数据),父进程还负责回收子进程

处理流程
1、创建socket,得到一个监听的文件描述符lfd–socket()
2、将lfd和IP和端口port进行绑定—bind()
3、设置监听—listen()
4、进入while(1)
{
//等待有新的客户端连接到来
cfd = accept();
//fork一个子进程,让子进程去处理数据
pid = fork();
if(pid<0)
{
exit(-1)
}
else if (pid>0)
{
//关闭通信文件描述符cfd
close(cfd)
}
else if (pid==0)
{
//关闭监听文件描述符
close(lfd)

						//收发数据
						while(1)
						{
									//读数据
									n = read(cfd,buf,sizeof(buf));
									if(n<=0)
									{
									break;
									}
									//发送数据给对方
									write(cfd,buf,n)
						}
						close(cfd);
						//下面的exit必须有,防止子进程再去创建子进程
						exit(0);
		}

}

注意点:accept或者read函数是阻塞函数,会被信号打断,此时不应该视为一个错误
创建子进程

知识改变命运

多线程并发服务器

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值