socket描述符

套接字是通信端点的抽象,创建一个套接字使用如下函数:

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

返回值:若成功,返回套接字描述符;若出错,返回-1

说明:

domain: 指定通信的特征,包括地址格式,以AF_开头的常数表示地址族(address family):

说明

AF_INET

IPv4因特网域

AF_INET6

IPv6因特网域

AF_UNIX

UNIX域

AF_UPSPEC

未指定(可以代表任何域)

 

 

 

 

 

 

 

 

 

type: 指定套接字的类型。如下为POSIX.1的套接字类型,也可以增加其他类型的支持:

类型

说明

SOCK_DGRAM

固定长度、无连接、不可靠

SOCK_RAM

IP协议的数据报接口

SOCK_SEQPACKET

固定长度、面向连接、有序、可靠

SOCK_STREAM

有序、可靠、双向、面向连接

 

 

 

 

 

 

 

 

 

protocol: 根据指定的domain和type所提供的默认协议,通常设为0即可。在AF_INET通信域中,SOCK_STREAM默认的协议为TCP;SOCK_DGRAM默认的协议为UDP。

 

使用无连接的数据报通信类似于邮寄信件,你不能保证传递的次序,信件可能会丢失,每封信都包含收信人地址;相反地,使用面向连接的通信协议类似于打电话,首先需要建立连接,连接建立好以后,彼此可以双向地通信,对话中不需要包含地址信息,连接本身指定了通话的源和目的,就像是端与端之间有一条虚拟链路一样。

SOCK_STREAM套接字提供了字节流服务,应用程序不能分辨出报文的界限;SOCK_SEQPACKET套接字提供了基于报文的服务,这意味着接受的数据量和发送的数据量完全一致;SOCK_RAW套接字提供了一个数据报接口,用于直接访问下面的网络层,使用该套接字时,必须有root用户权限,并且需要应用程序自己负责构造协议头。

 

套接字通信是双向的,可以使用shutdown函数来禁止一个套接字I/O:

#include <sys/socket.h>

int shutdown(int sockfd, int how);

返回值:若成功,返回0;若出错,返回-1。

说明:

how: SHUT_RD(关闭读),SHUT_WR(关闭写),SHUT_RDWR(关闭读写).

套接字是一个文件描述符,那么就可以使用close释放一个套接字。既然如此,为何还使用shutdown呢?首先,只有最后一个活动引用关闭时,close才释放网络端点。这意味着如果复制了一个套接字(dup),要直到关闭了最后一个引用它的文件描述符才会释放这个套接字。而shutdown允许使一个套接字处于不活动状态,和引用它的文件描述符数目无关。其次,有时可以很方便地关闭套接字双向传输中的一个方向。

 

补充:套接字本质上是一个文件描述符,如下为适用于文件描述符的函数在套接字中的表现行为:

函数

说明

close

释放套接字

dup / dup2

复制套接字

fchdir

失败,并且将errno设置为ENOTDIR

fchomod

未指定

fchown

由实现定义

fcntl

支持某些命令

fdatasync / fsync

由实现定义

fstat

支持一些stat结构成员,如何支持由实现定义

ftruncate

未指定

ioctl

依赖于底层设备驱动

lseek

由实现定义,失败时将errno设置为ESPIPE

mmap

未指定

poll

正常工作

pread / pwrite

失败时,将errno设置为ESPIPE

read / readv

与没有任何标志位的recv等价

select

正常工作

write / writev

与没有任何标志位的send等价

 

 

寻址

不同的处理器架构有着不同的字节序,如果需要实现异构通信,必须统一字节序方式。网络协议指定了字节序(网络字节序),TCP/IP协议栈使用大端方式,对于使用TCP/IP的应用程序,有4个函数可以用来在处理器字节序和网络字节序之间进行转换:

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostint32);  // 32位主机-->32位网络

uint16_t htons(uint16_t hostint16);  // 16位主机-->16位网络

uint32_t ntohl(uint32_t netint32); // 32位网络-->32位主机

uint16_t ntohs(uint16_t netint16); // 16位网络-->16位主机

说明:

h: 主机字节序

n: 网络字节序

l: 4字节的长整型

s: 2字节的短整型

 1 #include <arpa/inet.h>
 2 #include <stdio.h>
 3 
 4 int main(void)
 5 {
 6         unsigned int bytes = 0x12345678;
 7         const char* p = (const char*)&bytes;
 8         printf("%x_%x_%x_%x\n", p[0], p[1], p[2], p[3]);
 9 
10         unsigned int netbytes = htonl(bytes);    /* 将主机字节序转换为网络字节序 */
11         p = (const char*)&netbytes;
12         printf("%x_%x_%x_%x\n", p[0], p[1], p[2], p[3]);
13         
14         return 0;
15 }
16 
17 [root@benxintuzi benxin]# ./addr01
18 78_56_34_12
19 12_34_56_78
View Code

相关文章:

  • 2022-01-12
  • 2022-01-02
  • 2022-12-23
  • 2021-11-24
  • 2021-10-23
  • 2021-12-11
  • 2022-12-23
  • 2022-02-09
猜你喜欢
  • 2022-03-04
  • 2022-12-23
  • 2021-06-07
  • 2022-02-27
  • 2021-07-16
  • 2021-07-18
相关资源
相似解决方案