网络编程之bind()的未解之谜

初识bind()

     相信大家还记得我们之前写到的服务器函,下面博主还是给出之前服务前端的函数调用顺序。

服务器端:

socket()-->bind( )-->listen()-->accept()-->read()/write()--->close()

socket()//创建套接字
bind()//分配套接字地址
listen()//等待连接请求状态
accept()//允许连接
read()/write()//进行数据交换
close()//断开连接

     上一篇博客博主已经分享了socket()函数了,那么现在我们就来讲讲什么是bind()函数。

首先我们给出bind()函数各个参数的含义。

#include <sys/types.h> 
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数的含义
	第一个参数 int	sockfd:
			socket文件描述符
	第二个参数 const struct	addr:
			构造出IP地址加端口号
	第三个参数 socklen_t		addrlen:
			sizeof(addr)长度

返回值:
	成功返回0,失败返回-1, 设置errno

     服务器程序所监听的网络地址和端口号通常是固定不变的,客户端程序得知服务器程序的地址和端口号后就可以向服务器发起连接,因此服务器需要调用bind绑定一个固定的网络地址和端口号

      bind()的作用是将参数sockfd和addr(端口号和地址)绑定在一起,使sockfd这个用于网络通讯的文件描述符监听addr所描述的地址和端口号。addr参数实际上可以接受多种协议的sockaddr结构体,而它们的长度各不相同,所以需要第三个参数addrlen指定结构体的长度。

第一个参数

     第一个参数相信大家应该已经不陌生了。sockfd 就是在调用 socket()之后返回的socket文件描述符,为 int型,所以在用的时候,我们需要定义一个 int sockfd来接受。大家后面看服务器客户端的时候,也能明白前面的 int sockfd是什么意思了。就是为了接受socket()函数调用成功后返回的sockfd描述符。

第二个参数 const struct sockaddr *addr

这个函数比较复杂,这是一个传入参数。里面更是一层套一层。
下面是书中的(以后用的都是 struct sockaddr_in)至于为什么,这就牵扯到历史原因了,大家记住就好。
在这里插入图片描述
如果有小伙伴想要知道到底是什么历史原因博主也就在这里给大家分享一下:
如果有小伙伴想要知道到底是什么历史原因博主也就在这里给大家分享一下:

strcut sockaddr 很多网络编程函数诞生早于IPv4协议,那时候都使用的是sockaddr结构体,为了向前兼容,现在sockaddr退化成了(void *)的作用,传递一个地址给函数,至于这个函数是sockaddr_in还是sockaddr_in6,由地址族确定,然后函数内部再强制类型转化为所需的地址类型。

后续如 sockadd_in对以前的结构体的14字节进行了详细划分,但是却改变了结构体的名字,如果直接将这样的参数传给linux,linux是不认的,所以我们就需要改变他的类型。

目前涉及到要墙砖参数的三个函数:
acceot();
bind();
conect();

在这里插入图片描述

值域地址族啊什么的如果要说就有时一大段了,所以博主打算下面的博客再详细介绍。现在博主就先给大家介绍一下bind()函数如何使用,以及参数的大致含义即可。

第二个参数里面包含了 IP和端口号,以及你在使用socket()里面的第一个参数

int domain(协议)

也就意味着你的结构体里面的有一个参数和socket()里面的第一个参数是一致的。
那个参数就是

sa_family_t  sin_family;


剩下的两个参数就是 sin_port----->端口号 最后一个就是IP地址了。也就是它导致了结构体内部嵌套了一个结构体。具体原因就是网络中使用的是网络字节序,而我们常用的是点分十进制的IP表示,也就是下面的这种 在这里插入图片描述

而图片上也说明了,那里面的唯一参数就是存放 32位IPV4的地址的。

最后一个参数 socklen_t addrlen

就是为了描述第二个参数的大小而设计的 socklen其实就是利用typedef 的int型

大家在使用bind()函数之前 一般要的步骤是:

1.清空网路地址
2.把IP和端口号以及对应的协议绑定到结构体里面,然后再把结构体传入到bind()的第二个参数里面。
也就是一下代码

struct sockaddr_in servaddr;	//为了让bind()绑定IP和端口号而定义的


bzero(&serv_addr, sizeof(serv_addr));	//将网络地址清空
memset(&serv_addr,0,sizeof(serv_addr));//z这个方法也可以


servaddr.sin_family = AF_INET;//与socket()的第一个参数 int domain一样的协议
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);	//绑定IP
servaddr.sin_port = htons(6666);	//绑定端口号

bind(serv_addr, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

好了就跟新这么多吧,一般也就是这么写的了,最多在家判断条件而已,宿舍断电了,最后的都是博主抹黑打出来的,真的不容易啊、

后面的 htons这些 INADDR_ANY后续会讲到的。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
网络编程,当然要用到Windows Socket(套接字)技术。Socket相关的操作由一系列API函数来完成,比如socket、bind、listen、connect、accept、send、sendto、recv、recvfrom等。调用这些API函数有一定的先后次序,有些函数的参数还比较复杂,对于开发者来说,不是很好用。于是,微软的MFC提供了两个类:CAsyncSocket和CSocket,极大地方便了Socket功能的使用。   CAsyncSocket类在较低层次上封装了Windows Socket API,并且通过内建一个(隐藏的)窗口,实现了适合Windows应用的异步机制(Windows Socket API默认情况下工作在阻塞模式,不方便直接在消息驱动的Windows程序上使用)。CSocket类从CAsyncSocket类派生,进一步简化了Socket功能的应用。不过很遗憾,正因为这两个类都内建了一个窗口,它们并不是线程安全的(thread-safe);如果要在多线程环境下应用Socket功能,建议自行封装Socket API函数。 基于TCP的socket编程的服务器端程序流程如下: 1、创建套接字 2、将套接字绑定到一个本地地址和端口号上(bind) 3、将套接字设为监听模式,准备接受客户请求(listen) 4、等待客户请求,请求到来时接受请求,建立链接,并返回 一个新的基于此次通信的套接字(accept) 5、用返回的套接字和客户端进行通信(send、recv) 6、返回,等待另一客户请求 7、关闭套接字 基于TCP的socket编程的客户端程序流程如下: 1、创建套接字 2、向服务器端发送请求(connect) 3、和服务器端进行通信(send、recv) 4、关闭套接字 基于UDP的socket编程的服务器端程序流程如下: 1、创建套接字 2、将套接字绑定到本地地址和端口号上(bind) 3、等待接收数据(recvfrom) 4、关闭套接字 基于UDP的socket编程的客户端程序流程如下: 1、创建套接字 2、和服务器端进行通信(sendto) 3、关闭套接字 异步方式指的是发送方不等接收方响应,便接着发下个数据包的通信方式;而同步指发送方发出数据后,等收到接收方发回的响应,才发下一个数据包的通信方式。   阻塞套接字是指执行此套接字的网络调用时,直到成功才返回,否则一直阻塞在此网络调用上,比如调用recv()函数读取网络缓冲区中的数据,如果没有数据到达,将一直挂在recv()这个函数调用上,直到读到一些数据,此函数调用才返回;而非阻塞套接字是指执行此套接字的网络调用时,不管是否执行成功,都立即返回。比如调用recv()函数读取网络缓冲区中数据,不管是否读到数据都立即返回,而不会一直挂在此函数调用上。在实际Windows网络通信软件开发中,异步非阻塞套接字是用的最多的。平常所说的C/S(客户端/服务器)结构的软件就是异步非阻塞模式的。   对于这些概念,初学者的理解也许只能似是而非,我将用一个最简单的例子说明异步非阻塞Socket的基本原理和工作机制。目的是让初学者不仅对Socket异步非阻塞的概念有个非常透彻的理解,而且也给他们提供一个用Socket开发网络通信应用程序的快速入门方法。操作系统是Windows 98(或NT4.0),开发工具是Visual C++6.0。   MFC提供了一个异步类CAsyncSocket,它封装了异步、非阻塞Socket的基本功能,用它做常用的网络通信软件很方便。但它屏蔽了Socket的异步、非阻塞等概念,开发人员无需了解异步、非阻塞Socket的原理和工作机制。因此,建议初学者学习编网络通信程序时,暂且不要用MFC提供的类,而先用Winsock2 API,这样有助于对异步、非阻塞Socket编程机制的理解。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值