⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 套接口.txt

📁 这个资料非常不错
💻 TXT
📖 第 1 页 / 共 2 页
字号:
客户机可以通过套接口接收服务器传过来的数据,也可以通过套接口向服务器发送数据。前面所有的准备工作(创建套接口、绑定等操作)都是为这一步骤准备的。
常用的从套接口中接收数据的调用有:recv、recvfrom、recvmsg等,常用的向套接口中发送数据的调用有send、sendto、sendmsg等。

int recv(int s, void *buf, size_t len, int flags)
int recvfrom(int s,  void *buf,  size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
int recvmsg(int s, struct msghdr *msg, int flags)
int send(int s,const void *msg, size_t len, int flags)
int sendto(int s, const void *msg, size_t len, int flags const struct sockaddr *to, socklen_t tolen)
int sendmsg(int s, const struct msghdr *msg, int flags)

这里不再对这些调用作具体的说明,只想强调一下,recvfrom()以及recvmsg()可用于面向连接的套接口,也可用于面向非连接的套接口;而recv()一般用于面向连接的套接口。另外,在调用了connect()之后,就应给调用send()而不是sendto()了,因为调用了connect之后,目标就已经确定了。
前面讲到,socket()系统调用返回套接口描述字,实际上它是一个文件描述符。所以,可以对套接口进行通常的读写操作,即使用read()及write()方法。在实际应用中,由于面向连接的通信(采用TCP传输协议)是可靠的,同时又保证字节流原有的顺序,所以更适合用read及write方法。而非面向连接的通信(采用UDP传输协议)是不可靠的,字节流也不一定保持原有的顺序,所以一般不宜用read及write方法。
(6)通信的最后一步是关闭套接口
由close()来完成此项功能,它唯一的参数是套接口描述字,不再赘述。
4、典型调用代码:
到处可以发现基于套接口的客户机及服务器程序,这里不再给出完整的范例代码,只是给出它们的典型调用代码,并给出简要说明。
(1)典型的TCP服务器代码:


... ...
int listen_fd, connect_fd;
struct sockaddr_in serv_addr, client_addr;
... ...
listen_fd = socket ( PF_INET, SOCK_STREAM, 0 );
/* 创建网际Ipv4域的(由PF_INET指定)面向连接的(由SOCK_STREAM指定,如果创建非面向连接的套接口则指定为SOCK_DGRAM)的套接口。第三个参数0表示由内核确定缺省的传输协议,
对于本例,由于创建的是可靠的面向连接的基于流的套接口,内核将选择TCP作为本套接口的传输协议) */
bzero( &serv_addr, sizeof(serv_addr) );
serv_addr.sin_family = AF_INET ;  /* 指明通信协议族 */
serv_addr.sin_port = htons( 49152 ) ;       /* 分配端口号 */
inet_pton(AF_INET, " 192.168.0.11", &serv_addr.sin_sddr) ;
/* 分配地址,把点分十进制IPv4地址转化为32位二进制Ipv4地址。 */
bind( listen_fd, (struct sockaddr*) serv_addr, sizeof ( struct sockaddr_in )) ; /* 实现绑定操作 */
listen( listen_fd, max_num) ; /* 套接口进入侦听状态,max_num规定了内核为此套接口排队的最大连接个数 */
for( ; ; ) {
... ...
connect_fd = accept( listen_fd, (struct sockaddr*)client_addr, &len ) ; /* 获得连接fd. */
... ...													/* 发送和接收数据 */
}
注:端口号的分配是有一些惯例的,不同的端口号对应不同的服务或进程。比如一般都把端口号21分配给FTP服务器的TCP/IP实现。端口号一般分为3段,0-1023(受限的众所周知的端口,由分配数值的权威机构IANA管理),1024-49151(可以从IANA那里申请注册的端口),49152-65535(临时端口,这就是为什么代码中的端口号为49152)。
对于多字节整数在内存中有两种存储方式:一种是低字节在前,高字节在后,这样的存储顺序被称为低端字节序(little-endian);高字节在前,低字节在后的存储顺序则被称为高端字节序(big-endian)。网络协议在处理多字节整数时,采用的是高端字节序,而不同的主机可能采用不同的字节序。因此在编程时一定要考虑主机字节序与网络字节序间的相互转换。这就是程序中使用htons函数的原因,它返回网络字节序的整数。 
(2)典型的TCP客户代码:


... ...
int socket_fd;
struct sockaddr_in serv_addr ;
... ...
socket_fd = socket ( PF_INET, SOCK_STREAM, 0 );
bzero( &serv_addr, sizeof(serv_addr) );
serv_addr.sin_family = AF_INET ;  /* 指明通信协议族 */
serv_addr.sin_port = htons( 49152 ) ;       /* 分配端口号 */
inet_pton(AF_INET, " 192.168.0.11", &serv_addr.sin_sddr) ;
/* 分配地址,把点分十进制IPv4地址转化为32位二进制Ipv4地址。 */
connect( socket_fd, (struct sockaddr*)serv_addr, sizeof( serv_addr ) ) ; /* 向服务器发起连接请求 */
... ...													/* 发送和接收数据 */
... ...

对比两段代码可以看出,许多调用是服务器或客户机所特有的。另外,对于非面向连接的传输协议,代码还有简单些,没有连接的发起请求和接收请求部分。
5、网络编程中的其他重要概念
下面列出了网络编程中的其他重要概念,基本上都是给出这些概念能够实现的功能,读者在编程过程中如果需要这些功能,可查阅相关概念。
(1)、I/O复用的概念
I/O复用提供一种能力,这种能力使得当一个I/O条件满足时,进程能够及时得到这个信息。I/O复用一般应用在进程需要处理多个描述字的场合。它的一个优势在于,进程不是阻塞在真正的I/O调用上,而是阻塞在select()调用上,select()可以同时处理多个描述字,如果它所处理的所有描述字的I/O都没有处于准备好的状态,那么将阻塞;如果有一个或多个描述字I/O处于准备好状态,则select()不阻塞,同时会根据准备好的特定描述字采取相应的I/O操作。
(2)、Unix通信域
前面主要介绍的是PF_INET通信域,实现网际间的进程间通信。基于Unix通信域(调用socket时指定通信域为PF_LOCAL即可)的套接口可以实现单机之间的进程间通信。采用Unix通信域套接口有几个好处:Unix通信域套接口通常是TCP套接口速度的两倍;另一个好处是,通过Unix通信域套接口可以实现在进程间传递描述字。所有可用描述字描述的对象,如文件、管道、有名管道及套接口等,在我们以某种方式得到该对象的描述字后,都可以通过基于Unix域的套接口来实现对描述字的传递。接收进程收到的描述字值不一定与发送进程传递的值一致(描述字是特定于进程的),但是特们指向内核文件表中相同的项。
(3)、原始套接口
原始套接口提供一般套接口所不提供的功能:
* 原始套接口可以读写一些用于控制的控制协议分组,如ICMPv4等,进而可实现一些特殊功能。 
* 原始套接口可以读写特殊的IPv4数据包。内核一般只处理几个特定协议字段的数据包,那么一些需要不同协议字段的数据包就需要通过原始套接口对其进行读写; 
* 通过原始套接口可以构造自己的Ipv4头部,也是比较有意思的一点。 
创建原始套接口需要root权限。
(4)、对数据链路层的访问
对数据链路层的访问,使得用户可以侦听本地电缆上的所有分组,而不需要使用任何特殊的硬件设备,在linux下读取数据链路层分组需要创建SOCK_PACKET类型的套接口,并需要有root权限。
(5)、带外数据(out-of-band data)
如果有一些重要信息要立刻通过套接口发送(不经过排队),请查阅与带外数据相关的文献。
(6)、多播
linux内核支持多播,但是在默认状态下,多数linux系统都关闭了对多播的支持。因此,为了实现多播,可能需要重新配置并编译内核。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -