Linux网络编程---socket编程接口接口函数

发布时间:2024年01月16日

Linux网络编程—socket编程接口接口函数

使用 socket 接口需要在应用程序代码中包含两个头文件:

#include <sys/types.h> 
#include <sys/socket.h>

1 socket()函数

socket()函数原型如下所示:

#include <sys/types.h> 
#include <sys/socket.h>

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

??socket()函数类似于 open()函数,用于创建一个网络通信端点,如果成功则返回一个网络文件描述符,通常把这个文件描述符称为 socket 描述符,这个 socket 描述符与文件描述符一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。

  • domain
    1. 参数 domain 用于指定一个通信域,选择用于通信的协议族(AF_UNIX 和 AF_INET 等)。
    2. AF_UNIX 只能够用于单一的 Unix 系统进程间通信,而 AF_INET 是针对 Internet 的,可以允许远程通信使用。
  • type
    1. 参数 type 用于指定套接字的类型(SOCK_STREAM,SOCK_DGRAM 等)。
    2. SOCK_STREAM 表明用的是 TCP 协议,这样会提供按顺序的,可靠,双向,面向连接的比特流。
    3. SOCK_DGRAM 表明用的是 UDP 协议,这样只会提不可靠,无连接的通信。
  • protocol
    ??参数 protocol 通常设置为 0,表示为给定的通信域和套接字类型选择默认协议。当对同一域和套接字类型支持多个协议时,可以使用 protocol 参数选择一个特定协议。在 AF_INET 通信域中,套接字类型为SOCK_STREAM 的默认协议是TCP。在 AF_INET 通信域中,套接字类型为SOCK_DGRAM 的默认协议时 UDP。
  • 返回值
    ??调用 socket()与调用 open()函数类似,调用成功情况下,会返回用于文件 I/O 的文件描述符,但是对于 socket()来说,其返回的文件描述符一般称为 socket 描述符。当不再需要该文件描述符时,调用close()函数来关闭套接字,释放相应的资源。

此函数执行成功时返回文件描述符,失败时返回-1。

示例:

int socket_fd = socket(AF_INET, SOCK_STREAM, 0);//打开套接字
if (-1 == socket_fd)
{
	printf("socket error!\n");
	return -1;
}

......
......

close(socket_fd); //关闭套接字

2 bind 函数

函数原型如下所示:

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

bind()函数用于将一个 IP 地址或端口号与一个套接字进行绑定。

  • sockfd 是由 socket 函数调用返回的网络文件描述符。
  • addr 是一个指向 sockaddr 的指针。
  • addrlen 是 sockaddr 结构的长度。

sockaddr 的定义:

struct sockaddr{
unisgned short as_family;
char sa_data[14];
};

这个结构对用户并不友好,它把这些信息都封装在了 sa_data 数组中,不过由于系统的兼容性 , 我们一般使用另外一个结构 (struct sockaddr_in) 来代替。

sockaddr_in 的定义:

struct sockaddr_in{
unsigned short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
}

如果使用 Internet 所以 sin_family 一般为 AF_INET。

  • sin_port 是要监听的端口号。
  • sin_addr 设置为 INADDR_ANY 表示可以和任意的主机IP通信。
  • bind 将本地的端口同 socket 返回的文件描述符捆绑在一起,成功是返回 0,失败返回-1。

??调用 bind()函数将参数 sockfd 指定的套接字与一个地址 addr 进行绑定,成功返回 0,失败返回-1。
使用示例:

struct sockaddr_in socket_addr;
memset(&socket_addr, 0x0, sizeof(socket_addr)); //清零
//填充变量
socket_addr.sin_family = AF_INET;
socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
socket_addr.sin_port = htons(8888);
//将地址与套接字进行关联、绑定
bind(socket_fd, (struct sockaddr *)&socket_addr, sizeof(socket_addr));

3 listen 函数

??listen()函数只能在服务器进程中使用,让服务器进程进入监听状态,等待客户端的连接请求,listen()函数在一般在 bind()函数之后调用,在 accept()函数之前调用,它的函数原型是:

int listen(int sockfd,int backlog);
  1. 参数 backlog 用来描述 sockfd 的等待连接队列能够达到的最大值。
  2. 在服务器进程正处理客户端连接请求的时候,可能还存在其它的客户端请求建立连接,因为 TCP 连接是一个过程,由于同时尝试连接的用户过多,使得服务器进程无法快速地完成所有的连接请求。
  3. 因此内核会在自己的进程空间里维护一个队列,这些连接请求就会被放入一个队列中,服务器进程会按照先来后到的顺序去处理这些连接请求,这样的一个队列内核不可能让其任意大,所以必须有一个大小的上限,这个 backlog 参数告诉内核使用这个数值作为队列的上限。
  4. 当一个客户端的连接请求到达并且该队列为满时,客户端可能会收到一个表示连接失败的错误,本次请求会被丢弃不作处理。

4 accept 函数

??服务器调用 listen()函数之后,就会进入到监听状态,等待客户端的连接请求,使用 accept()函数获取客户端的连接请求并建立连接。函数原型如下所示:

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

为了能够正常让客户端能正常连接到服务器,服务器必须遵循以下处理流程:

  1. 调用 socket()函数打开套接字;
  2. 调用 bind()函数将套接字与一个端口号以及 IP 地址进行绑定;
  3. 调用 listen()函数让服务器进程进入监听状态,监听客户端的连接请求;
  4. 调用 accept()函数处理到来的连接请求。

??accept函数通常只用于服务器应用程序中,如果没有客户端请求连接,此时accept函数会进入阻塞状态,直到有客户端连接请求为止。
??当有客户端连接请求到达时,accept函数会与远程客户端建立连接,并且返回一个新的套接字,这个新的套接字与socket函数返回的套接字不同,我们后续与客户端进行数据交互是通过这个套接字。
??参数addr是一个传出参数,参数 addr 用来返回已连接的客户端的 IP 地址与端口号等这些信息。
??函数执行成功返回新的套接字,失败返回-1。

5 connect 函数

connect 函数的函数原型如下所示:

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

??该函数用于客户端应用程序中,客户端调用 connect()函数将套接字 sockfd 与远程服务器进行连接,参数 addr 指定了待连接的服务器的 IP 地址以及端口号等信息,参数 addrlen 指定了 addr 指向的 struct sockaddr对象的字节大小。
??客户端通过 connect()函数请求与服务器建立连接,对于 TCP 连接来说,调用该函数将发生 TCP 连接的握手过程,并最终建立一个 TCP 连接,而对于 UDP 协议来说,调用这个函数只是在 sockfd 中记录服务器 IP 地址与端口号,而不发送任何数据。
??成功时返回 0,失败时返回-1。

6 send 函数

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • sockfd 指定发送端套接字描述符;
  • buf 指明一个存放应用程序要发送数据的缓冲区;
  • len 指明实际要发送的数据的字节数;
  • flags 一般置 0。
  • 客户或者服务器应用程序都用 send 函数来向 TCP 连接的另一端发送数据

7 recv 函数

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
  • sockfd 指定接收端套接字描述符;
  • buf 指明一个缓冲区,该缓冲区用来存放 recv 函数接收到的数据;
  • len 指明 buf 的长度;
  • flags 一般置 0。
  • 客户或者服务器应用程序都用 recv 函数从 TCP 连接的另一端接收数据。

8 recvfrom 函数

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
  • recvfrom 通常用于无连接套接字,因为此函数可以获得发送者的地址。
  • src_addr 是一个 struct sockaddr 类型的变量,该变量保存源机的 IP 地址及端口号。
  • addrlen 常置为 sizeof (struct sockaddr)。

9 sendto 函数

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
  • sendto 和 send 相似,区别在于 sendto 允许在无连接的套接字上指定一个目标地址。
  • dest_addr 表示目地机的 IP 地址和端口号信息。
  • addrlen 常置为 sizeof (struct sockaddr)。
文章来源:https://blog.csdn.net/weixin_47268803/article/details/135552921
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。