失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > socket 编程入门教程(一)TCP server 端:5 创建监听嵌套字

socket 编程入门教程(一)TCP server 端:5 创建监听嵌套字

时间:2022-08-14 06:16:50

相关推荐

socket 编程入门教程(一)TCP server 端:5 创建监听嵌套字

前面一小节,我们已经写出了TcpServer的构造函数。这个函数的实际作用,就是创建了listen socket(监听嵌套字)。这一节,我们来具体分析这个创建的过程。

socket和sockaddr的创建是可以相互独立的

在函数中,我们首先通过socket()系统调用创建了listenSock,然后通过为结构体赋值的方法具体定义了服务器端的sockaddr。(memset()函数的作用是把某个内存段的空间设定为某值,这里是清零。)其他的概念已经在前一小节讲完了。这里需要补充的是说明宏定义INADDR_ANY。这里的意思是使用本机所有可用的IP地址。当然,如果你机器绑定了多个IP地址,你也可以指定使用哪一个。

数据流简易模型(SOCK_STREAM)

我们的例子以电话做的比喻,实际上,socket stream模型不完全类似电话,它至少有以下这些特点:

1、一种持续性的连接。这点跟电话是类似的,也可以想象成流动着液体的水管。一旦断开,这种流动就会中断。

2、数据包的发送实际上是非连续的。这个世界上有什么事物是真正的线性连续的?呵呵,扯远了,这貌似一个哲学问题。我们仅仅需要知道的是,一个数据包不可能是无限大的,所以,总是一个小数据包一个小数据包这样的发送的。这一点,又有点像邮包的传递。这些数据包到达与否,到达的先后次序本身是无法保证的,即是说,是IP协议无法保证的。但是stream形式的TCP协议,在IP之上,做了一定到达和到达顺序的保证。

3、传送管道实际上是非封闭的。要不干嘛叫“网络”-_-!!!。我们之所以能保证数据包的“定点”传送,完全是依靠每个数据包都自带了目的地址信息。

由此可见,虽然socket和sockaddr可以分别创建,并无依赖关系。但是在实际使用的时候,一个socket至少会绑定一个本机的sockaddr,没有自己的“地址信息”,就不能接受到网络上的数据包(至少在TCP协议里面是这样的)。

socket与本机sockaddr的绑定

有时候绑定是系统的任务,特别是当你不需要知道自己的IP地址和所使用的端口号的时候。但是,我们现在是建立服务器,你必须告诉客户端你的连接信息:IP和Port。所以,我们需要指明IP和Port,然后进行绑定。

intbind(intsocket,structsockaddr*localAddress,unsignedintaddressLength); 作为C++的程序员,也许你会觉得这个函数很不友好,它似乎更应该写成:

intbind_cpp_style(intsocket,constsockaddr&localAddress); 我们需要通过函数原型指明两点:

1、我们仅仅使用sockaddr结构的数据,但并不会对原有的数据进行修改;

2、我们使用的是完整的结构体,而不仅仅是这个结构体的指针。(很显然光用指针是无法说明结构体大小的)

幸运的是,在Linux的实现中,这个函数已经被写为:

#include<sys/socket.h>

/*GivethesocketFDthelocaladdressADDR(whichisLENbyteslong).*/

externintbind(int__fd,__CONST_SOCKADDR_ARG__addr,socklen_t__len)

__THROW; 看到亲切的const,我们就知道这个指针带入是没有“副作用”的。

监听:listen()

stream流模型形式上是一种“持续性”的连接,这就是要求信息的流动是“可来可去”的。也就是说,stream流的socket除了绑定本机的sockaddr,还应该拥有对方sockaddr的信息。在listen()中,这“对方的sockaddr”就可以不是某一个特定的sockaddr。实际上,listen socket的目的是准备被动的接受来自“所有”sockaddr的请求。所以,listen()反而就不能指定某个特定的sockaddr。

intlisten(intsocket,intqueueLimit); 其中第二个参数是等待队列的限制,一般设置在5-20。Linux中实现为:

#include<sys/socket.h>

/*PreparetoacceptconnectionsonsocketFD.

Nconnectionrequestswillbequeuedbeforefurtherrequestsarerefused.

Returns0onsuccess,-1forerrors.*/

externintlisten(int__fd,int__n)__THROW; 完成了这一步,回到我们的例子,就像是让你小弟在电话机前做好了接电话的准备工作。需要再次强调的是,这些行为仅仅是改变了socket的状态,实际上我想强调的是,为什么这些函数不会造成block(阻塞)的原因。(block的概念以后再解释)

如果觉得《socket 编程入门教程(一)TCP server 端:5 创建监听嵌套字》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。