socket通信函数的深入分析

      平时我们可能会用 socket 通信做个作业交给老师,一般情况下,都是拷贝一段代码,ip 地址改下,端口号改下也就可以了,即使是会写 socket 通信程序,甚至是使用 socket 做一个文件传输的东西也不一定知晓 socket 通信函数的内部实现原理,这篇文章我就介绍下这些函数的内部实现:

      1.socket

      这个函数是通信的开端。当我们使用这个函数并指定了协议类型之后,这个时候称为已经打开了通信端口,注意,这个时候的通信端口是主动的,也就是想去连接服务器的那种。

      我们需要知道,socket 其实是个三元组:协议,端口和ip地址。这个socket位于应用层,它调用下层的接口实现功能,socket 可以随意指定,它也是不确定的,毕竟它就是存在与文件系统中的一个文件,而 socket 函数返回的正式这个文件的描述符。

      端口,我们知道,端口这个东西就是一个数字,一般这个数字会大于 1024(我们的应用程序使用)。不过,就这样一个数字就能标识一个进程吗?毕竟,进程有进程id呀。其实,端口在内核中的实现是一个队,进程对应着这个队,当进程收到数据后会从这个被数字标识的队取得数据,这样的话就不会乱了,进程对应着它的队,每个进程都有,所以说,端口对应着计算机中的进程。

      ip地址,这个就不用多说了,毕竟在教科书中始终说着它是世界上独一无二的东西。


      2.bind

      我们知道,这个函数一般是用在服务器端,为什么呢?因为服务器是让客户端去连接的主体,而建立连接需要端口号和ip地址,如果不绑定这个端口号,内核会随便选择一个并绑定,而我们不知道那个是什么(当然,是有办法获取的),所以,我们需要一个已知的端口,且要告诉客户端端口号是什么。

      有时,我们调试程序可以发现,重新运行服务器时会出现端口地址冲突,这是因为,程序一结束的时候,套接字处于 TIMEWAIT 阶段,端口号并没有释放,所以,会出现冲突,这个时候我们需要调用函数 setscokopt ,并使用参数 SO_REUSEADDR, 说明地址重用即可。

      我们选择的端口号需要大于1024,因为小于1024的端口被用来作为一些互联网上的熟知应用。当然,也不一定是不能用的,这个时候你只需要加入 root 权限就可以了,不过,一般不建议这样做。


      3.listen

      上面我说过,socket 函数使得这个端口变为主动,这个函数呢?功能正是我们想要的,让这个程序称为服务器,也就是被动打开的意思,让需要连接的套接字连接服务器。

      我们知道,这个函数存在一个 backlog 的参数,这个参数的意思是可连接的客户端的最大数目。这个是怎么实现的呢?

      当我们调用这个函数时,内核为我们创建了两个队列,一个叫做未完成连接队列,这个队列中存在的是收到 客户端的 SYN 分节,但是还没响应的连接;另一个队列叫做以完成连接队列,这个队列中存在的是给客户返回了 ACK 之后连接建立的情况。这两个队列中的节点个数不应该超过 backlog。不过,各种实现不是相同的,有的实现即使是 backlog = 0,也可以接受客户端的连接,所以,我们尽量不要把这个参数写错就可以了。


      4.accept

      这个函数是阻塞函数,它其实扮演的是一个检查者的身份,它会不断检查 listen 函数建立的链表--以完成连接链表,并返回其中的节点,如果,这个链表是空的,那么这个函数就阻塞了,阻塞到直到有连接建立时。我们需要知道的是 TCP 的三次握手并不是在这个函数中完成的,而是在listen 函数中实现的,这个函数只是检查那三次握手成功了没有,如果成功了,这个函数会创建一个连接套接字,这个套接字不同于监听套接字(socket函数创建的),它标识的是与远端客户建立的连接,其中含有相应的信息,之后它会返回这个套接字用于通信。


      5.connect

      这个函数使用在客户端,我们从名字就能看出来,它是用于建立连接的,也就是连接服务器用的。没错,TCP的三次握手的开端就发生在这个函数中,不过,需要我们注意的是,客户端的连接完成是早于服务器的,因为,在服务器给客户端发送 SYN = 1,ACK = 1分节之后,客户端就进入了 ESTABLISHED的状态,而服务器是在客户端发送 ACK = 1之后才进入连接状态的。第一个分节和第三个分节都发生在这个函数中,所以,可以说它是客户端的最主要函数。


      由于服务器和客户端通信函数,也就是write,read。。。,这些个函数比较简单,也和文件的读写方式类似,在这里就不多做介绍了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值