TCP_网络编程(一)

TCP编程方式

服务端

//只说明大概流程,内部参数没有写详细
int fd = socket(); //创建套接字
bind(ip)//绑定当前的ip地址
listen(); //监听有谁连接
//listen(sockfd, 5)
//三次握手时,
//服务器会接收到2次数据,分别放入全连接队列和半连接队列两个队列中。
//linux中:两个队列的总和最大数
//uninx中:全连接队列的总和最大数
clientfd = accept(); //接受连接,返回在服务器端的代指所连接的客户端套接字
//第二个参数是:客户端的ip,实际上是网关的ip地址,而不是局域网的ip地址

recv(clientfd); //从客户端接收信息
send(clientfd); //给客户端发送信息
close(); //关闭套接字

客户端

bind(); 
connect(); //链接服务器端
send();
recv();
close();

recv < 0
1、io为非阻塞时,recv读空数据时,会返回-1
2、io为阻塞时,recvbuf中是空数据是不会返回的。
recv = 0
代表服务器和客户端断开了。
系统出现了大量close_wait是什么情况?
四次挥手时被动关闭方(服务器)收到fin包时,recv会返回0.
服务器主动调用close()函数时,客户端才会收到close_wait().
出现大量的close_wait,是我们调用recv返回0时,却没有及时调用close()造成的。
tcp中客户端与服务器有建立连接之后accept(),再进行交流。这样可以进行并发。但是udp如何进行并发呢?

UDP并发

背景:服务器端只有一个fd,却要处理多个客户端的数据。当成千上万个客户端数据过来时,udp服务器如何区分?如何同时做通讯?也就是如何做到多个客户端并发?

//udp服务器端流程
fd = socket();
recvfrom(fd,addr,buffer,...);
sendto();

方法一:
对buffer数据包加层稳定的协议,使其自带来处客户端的信息,表明身份。此方法的前提是数据是顺序接收的,
但是再公网条件下,udp难保证数据先发的先到,后发的后到。发送数据是无序的。此方法不可行。
方法二:仿照Tcp模式实现
创建socket,等待着迎宾,当其接收到第一个数据后,再创建独有的socket来与其专门通信。

socket是什么?

socket是什么?
本质是一个唯一的数字,其
由文件fd+网络资源数值化 (也就是五元组:源ip/端口 + 目ip/端 口 + 传输协议(tcp或者udp))组成

fd 是一个socket句柄,可以看做是一个文件,在socket上收发数据,相当于对一个文件进行读写,所以一个socket句柄,通常也用表示文件句柄的fd来表示

fd可当作文件描述符,也可当作客户端。
接下来介绍文件描述符的属性也就是io属性,也就是内存和外设的通信属性。
内核检测到文件读写就会发送sigIO。

什么是sigIO 信号

背景:网卡接收到数据就会通知操作系统发出sigIO消息。
只要fd读写就发出sigIO信号,那TCP是否也可以实现do_sigio处理信号函数?
理论上tcp可发出,但是不建议这么做,因为与dup相比,tcp处理数据时产生了更多的信号。

sigIO 信号如何工作的?(面试)

从三点回答:
1、进程的信号如何保存?
2、信号如何保存在进程中?
3、信号如何发送的,或者进程如何捕获到信号的?

信号接收的流程是什么?

1、进程结构体task_struct中的sighand_struct,action数组中存储的就是各种io信号。每个进程中有结构体sigaction数组,叫action,大小为64,里面存储了信号集合
在这里插入图片描述
在这里插入图片描述

2、有信号时系统调用内核函数将sigIO信号,就会将存储再action[sigIO-1]位置处;
3、当给某个进程发信号时,进程action[sigIO-1]等待的条件满足后,就去执行对应的回调函数。
kill实际调用kill_something_info(pid, sig)pid是进程,sig是信号,函数就是给哪个进程发什么信号。走到最里面的话send_signal、最后走到signalfd_notify()通知的意思,里面是个中断其实就是信号等待。
就是发送sigio时,进程中action中等待对应的sigio,等待条件满足后,就去执行对应的回调函数。

参考一

select/poll/epoll

背景:处理多种信号
select,poll,epoll都是IO多路复用的机制。I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间.
参考二

seleect

三个集合

select();
//参数:
//总数量IO,个数为MAX(fd)+1
//可读的IO集合,
//可写的IO集合,
//出错的IO集合,
//timeout,轮询的时间

poll

一个集合

poll();
//参数
//pfd,
//length, pfd数组长度,
//timeout

epoll

epoll_create();
epoll_ctr();
epoll_wait();
//int nready = epoll_wait(epfd, events, 512, -1);
//第二个参数:能够检测到事件的容器;
//第三个参数:容器的容量,也就是最大一次性检测多少个事件;
//第四个参数:多久轮询检测一次,-1代表有数据来才检测
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值