Linux C socket API 介绍

简介: Socket英文愿意是“插孔”或“插座”,作为BSD UNIX的进程通信机制后,取后一种意思,通常也被称为套接字。使用TCP/IP协议的应用程序通常采用的应用编程是使用UNIX BSD的套接字Socket,来实现网络进程之间的通信。

Socket 基础


Socket概念

Socket英文愿意是“插孔”或“插座”,作为BSD UNIX的进程通信机制后,取后一种意思,通常也被称为套接字。使用TCP/IP协议的应用程序通常采用的应用编程是使用UNIX BSD的套接字Socket,来实现网络进程之间的通信。


Socket用于描述IP地址和端口,是一个通信链的句柄,用来实现不同虚拟机或物理机之间的通信。应用程序通过Socket向网络发出请求或应答请求。网络中两个进程通过一个双向的通信连接实现数据的交换,建立网络通信连接至少需要一对Socket,连接的一端称为一个Socket。


具有唯一标识的网络进程可利用 Socket 进行通信,而 Socket 是在应用层和传输层之间的一个抽象层,Socket把TCP/IP层复杂的操作抽象为简单的接口供应用层调用,以实现进程在网络中的通信。TCP/IP协议存在于操作系统中,网络服务是通过操作系统提供的,因此在操作系统中增加支持TCP/IP的系统调用Socket。


socket 通信流程

在Linux系统中,一切皆文件,Socket也不例外,对socket的操作实际上也是对某种特殊文件的读写操作。只不过操作的文件在服务器和客户端各自拥有一个。

下图是最基本的socket 通信流程,也就是最初的网络I/O模型(阻塞I/0模型),注意这里展示的是TCP通信流程。

db7821754978d87aba3a308fcaefa3b8_watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYWJjZDU1MjE5MTg2OA==,size_20,color_FFFFFF,t_70,g_se,x_16.png

服务器端:

1.生成一个监听的socket,绑定IP地址和端口号

2.监听客户端的请求,并接受客户端的连接


客户端:

1.创建通信socket,

2.连接到服务器


客户端与服务器通信:

1.客户端连接成功向服务器发送连接状态信息

2.服务器端Accetp返回连接socket

3.客户端使用socket写入数据

4.服务器使用连接socket来接收数据


Socket API

创建socket

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

1

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

domain

协议簇/域,通常为AF_INET(IPv4)、AF_INET6(IPv6)

type

套接字类型,主要是SOCK_STREAM(TCP)、SOCK_DGRAM(UDP),另外包括SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。

protocol

顾名思义,就是指定协议。套接口所用的协议。如调用者不想指定,可用0。常用的协议有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

返回值

success 返回大于0 的socketfd值,错误, 返回-1, 使用errno得到错误值。

socket绑定

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

将socket和对应的端口和地址进行绑定,一般用于绑定服务器的监听socket,以便能够让客户端连接到服务器对应的ip和端口。

sockfd

使用socket接口创建的socket文件描述符

addr

服务器端的通信地址

其中参数的结构体如下表示

struct sockaddr{
  sa_family_t sa_family;
  char  sa_data[14];
};

addrlen

参数addr的长度

返回值

bind函数调用成功返回0,否则返回-1,并设置erro;

listen

int listen(int sockfd, int backlog);

服务器端使用listen接口来监听客户端的连接

sockfd

使用socket接口创建的socket文件描述符

backlog

backlog通常被描述为连接队列的限制,理解这个参数需要和accept接口一起,一般accept会返回一个sockfd,如果服务器一直没有调用accpet接口,每次有客户端的连接,那么连接队列就会增加1,那么当连接的队列数达到backlog的数字,那么服务器就不会在监听其他客户端的连接。

返回值

bind函数调用成功返回0,否则返回-1,并设置erro;

connect

int connect(int sockfd, const struct sockaddr *addr,  socklen_t addrlen);

该接口用于客户端连接服务器

sockfd

使用socket接口创建的socket文件描述符

serv_addr

该参数是可传入的实际结构体为sockaddr_in和sockadd_in6

sockaddr_in:该结构体存有将要connect的ipv4的网络地址以及端口和协议族

sockaddr_in6:该结构体存有将要connect的ipv6的网络地址以及端口和协议族

addrlen

为传入参数sockaddr结构体的大小,该参数实际应该是一个传出参数。

返回值

0-连接成功,-1连接服务器失败。错误值使用errno记录。

accept

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

主要用于服务器端接收客户端的连接,当客户端发起连接请求后,accept会返回当前连接客户端的socket信息。


参数同connect 接口

-返回值

成功,返回一个socketfd,这个socketfd记录了连接客户端的信息,服务器使用这个socket同客户端进行通信。

recv/recvfrom
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

recv和recvfrom主要用于接收对等端发送的信息,接收的信息存储于buf参数中。

recvfrom与recv不同之处的主要是前者多了2个参数,src_addr和addrlen,从参数名字就知道这2个参数主要是用于表示该请求的发送者的地址信息,由于UDP通信一般不需要客户端先连接服务器,因此recvfrom通常用于UDP通信,recv用于TCP通信。


sockfd

对于服务器端,sockfd为accept接口返回的socket(注意这个sockfd不为服务器使用socket接口生成的socket),对于客户端,为socket接口生成的socket信息。

buf

存放要发送数据的缓冲区

len

存放发送数据缓冲区的字节大小

flags

接收数据的参数设置信息,一般设置为0,主要有以下几个值(很少用)

MSG_DONTWAIT:仅支持非阻塞的socket,如果socket为阻塞的,会报EAGAIN 或者 EWOULDBLOCK错误

MSG_OOB:发送或者接收带外数据

MSG_WAITALL:等待请求的所有数据到达后才返回

MSG_PEEK:窥探请求发送的数据类型,主要用于查看请求的前几个字节,判断是文本协议还是二进制协议,然后再针对不同的协议来做不同的操作。

src_addr

消息发送方的地址信息

addrlen

src_addr地址信息的长度

返回值

成功,返回接收到的实际字节数,错误,返回-1,错误码可以通过errno获取到

send/sendto

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);

send/sendto主要用于发送消息给对等方,send主要用于TCP通信,sendto主要用于UDP通信。


sockfd

参数同recv/recvfrom接口的第一个参数信息

buf

要发送的缓冲区信息

len

要发送的缓冲字节长度

flags

主要设置发送信息的标志,一般设置为0,其他标志主要有

MSG_DONTROUTE:告诉内核,目标主机在本地网络,不用查路由表


MSG_DONTWAIT:将单个I/O操作设置为非阻塞模式


MSG_OOB:指明发送的是带外信息


dest_addr

要发送的目标地址信息

addrlen

发送的目标地址长度

其他接口

write()

read()

close():关闭socket

gethostbyname():IPv4专用

gethostbyaddr():IPv4专用

getsocketopt()获取对应socket的选项值

setsocketopt()设置对应socket的选项值

socket api 测试代码

Linux C TCP编程(socket编程)


相关文章
|
5月前
|
网络协议 算法 Linux
【嵌入式软件工程师面经】Linux网络编程Socket
【嵌入式软件工程师面经】Linux网络编程Socket
162 1
|
1月前
|
网络协议 Linux 网络性能优化
Linux基础-socket详解、TCP/UDP
综上所述,Linux下的Socket编程是网络通信的重要组成部分,通过灵活运用TCP和UDP协议,开发者能够构建出满足不同需求的网络应用程序。掌握这些基础知识,是进行更复杂网络编程任务的基石。
106 1
|
3月前
|
存储 Linux API
Linux源码阅读笔记08-进程调度API系统调用案例分析
Linux源码阅读笔记08-进程调度API系统调用案例分析
|
3月前
|
Linux API
Linux源码阅读笔记07-进程管理4大常用API函数
Linux源码阅读笔记07-进程管理4大常用API函数
|
3月前
|
Linux Python
【Azure 应用服务】Azure App Service For Linux 上实现 Python Flask Web Socket 项目 Http/Https
【Azure 应用服务】Azure App Service For Linux 上实现 Python Flask Web Socket 项目 Http/Https
|
3月前
|
开发框架 Unix Linux
LangChain 构建问题之在Unix/Linux系统上设置OpenAI API密钥如何解决
LangChain 构建问题之在Unix/Linux系统上设置OpenAI API密钥如何解决
50 0
|
3月前
|
应用服务中间件 Linux API
Linux 利用 Cloudflare API 配置 acme.sh 自动续签 SSL (Apache、Nginx适用)
安装acme.sh工具,命令为`curl https://get.acme.sh | sh -s email=你的邮箱`。接着配置Cloudflare API,创建并记录API令牌及Zone ID。最后通过`acme.sh --issue -d 你的域名 --dns dns_cf`签发SSL证书,对于Nginx可使用`acme.sh --install-cert`命令安装证书,并设置自动重载Nginx服务。
|
6月前
|
算法 Linux 调度
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
460 1
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
|
6月前
|
Linux API
Linux系统编程之文件编程常用API回顾和文件编程一般步骤
Linux系统编程之文件编程常用API回顾和文件编程一般步骤
Linux系统编程之文件编程常用API回顾和文件编程一般步骤
|
6月前
|
网络协议 Ubuntu Unix
Linux 下使用 socket 实现 TCP 客户端
Linux 下使用 socket 实现 TCP 客户端
189 1