socket()编程接口及编程实践

本文详细介绍了socket编程接口,包括socket()、bind()、listen()、connect()、accept()、read()、write()等核心函数的使用,以及辅助函数的作用。通过示例和流程解析,阐述了socket编程的基本原理和实践操作,帮助读者深入理解网络通信过程。
摘要由CSDN通过智能技术生成

Socket本身有“插座”的意思,在Linux环境下,用于表示进程间网络通信的特殊文件类型本质为内核借助缓冲区(队列)形成的伪文件。既然是文件,那么理所当然的,我们可以使用文件描述符引用套接字。与管道类似的,Linux系统将其封装成文件的目的是为了统一接口,使得读写套接字和读写文件的操作一致。区别是管道主要应用于本地进程间通信,而套接字多应用于网络进程间数据的传递。

在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程。“IP地址+端口号”就对应一个socket。欲建立连接的两个进程各自有一个socket来标识,那么这两个socket组成的socket pair就唯一标识一个连接。因此可以用Socket来描述网络连接的一对一关系。

套接字通信原理如下图所示

在网络通信中,套接字一定是成对出现的。一端的发送缓冲区对应对端的接收缓冲区。我们使用同一个文件描述符索发送缓冲区和接收缓冲区。

(一)基本的socket接口函数

socket()函数

socket函数类似于open,用来打开一个网络连接,如果成功则返回一个网络文件描述符(int类型),之后我们操作这个网络连接都通过这个网络文件描述符。

(1)函数原型

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

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

(2)参数

   ①domain: 指明所使用的协议族,通常为AF_INET,表示互联网协议族(TCP/IP协议族) 

  • AF_INET           IPv4因特网域
  • AF_INET6         IPv6因特网域
  • AF_UNIX           UNIX域
  • AF_ROUTE      路由套接字
  • AF_KEY           密钥套接字
  • AF_UNSPEC   未指定
  • 协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。

  ②type参数指定socket的类型: 

  • SOCK_STREAM:流式套接字提供可靠的、面向连接的通信流;它使用TCP 协议,从而保证了数据传输的正确性和顺序性
  • SOCK_DGRAM :数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议UDP
  • SOCK_RAW:允许程序使用低层协议,原始套接字允许对底层协议如IP或ICMP进行直接访问,功能强大但使用较为不便,主要用于一些协议的开发。

   ③protocol 

  • 通常赋值”0“。 
  • 0 选择type类型对应的默认协议
  • IPPROTO_TCP     TCP传输协议
  • IPPROTO_UDP     UDP传输协议
  • IPPROTO_SCTP   SCTP传输协议
  • IPPROTO_TIPC    TIPC传输协议
  • 注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。

(3)返回值

  • 成功,返回一个整型socket描述符,可以在后面的调用中使用它。socket描述符是一个整数,但它指向内部数据结构(socket结构)的指针,它指向描述符表入口。调用socket函数时,socket执行体将建立一个socket结构,实际上建立一个socket意味着为一个socket数据结构分配存储空间。socket执行体为你管理描述符表。该空间还有许多成员,并不会在初始化时被填充,可调用其它函数进行填充完善。 失败,返回-1。
  • 两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。socket数据结构中包含这五种信息。

bind()函数

bind()函数把一个地址族中的特定地址赋给socket。例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。(用于绑定IP地址和端口号到socketfd

端口号实质就是一个数字编号,用来在我们一台主机中(主机的操作系统中)唯一的标识一个能上网的进程端口号和IP地址一起会被打包到当前进程发出或者接收到的每一个数据包中。每一个数据包将来在网络上传递的时候,内部都包含了发送方和接收方的信息(就是IP地址和端口号),所以IP地址和端口号这两个往往是打包在一起不分家的。

(1)函数原型

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

(2)参数

  1.  sockfd:即socket描述符,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。
  2.  addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同。
  3. addrlen对应的是地址的长度,常被设置为sizeof(struct sockaddr)
//ipv4对应的是: 
struct sockaddr
{
    unisgned short  as_family;    // 协议族
    char            sa_data[14];  // IP+端口
};
同等替换:
struct sockaddr_in 
{
    sa_family_t    sin_family; /* 协议族  */
    in_port_t      sin_port;   /* 端口号*/
    struct in_addr sin_addr;   /*IP地址结构体*/
    unsigned char  sin_zero[8];  /* 填充   没有实际意义,只是为跟sockaddr结构在内存中对齐,这样两者才能相互转换*/
};
/*两个结构是等同的可以先互转换,第一个结构将地址和端口绑定了,第二个结构将两者分开表示*/

/* IP地址结构如下:为32位字 */
struct in_addr 
{
    uint32_t       s_addr;     /* address in network byte order */
};

//ipv6对应的是: 
struct sockaddr_in6 
{ 
    sa_family_t     sin6_family;   /* AF_
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值