文章目录
1、Posix API简介
POSIX(Portable Operating System Interface) 是一个为操作系统提供标准化接口的系列规范,旨在确保程序在不同 UNIX 操作系统和兼容系统之间具有可移植性。POSIX API 是一组标准的系统调用和库函数,它们定义了程序与操作系统交互的接口。POSIX API 主要涉及文件操作、进程管理、线程管理、信号处理、网络通信等方面。
2、Posix 网络 API简介
POSIX 网络 API 是一组标准化的接口,主要用于在 UNIX 和类 UNIX 操作系统(如 Linux、macOS)上进行网络编程。它们允许程序员创建、管理和通信网络套接字。POSIX 网络 API 通常基于 Berkeley 套接字(BSD Sockets)API,其主要功能包括套接字创建、绑定、监听、连接、发送和接收数据等。
3、API 具体介绍
(1)套接字(socket)
套接字是网络通信的基本单元,通过它,应用程序可以发送和接收数据。POSIX 提供了一系列函数来操作套接字。
socket()
创建一个新的套接字。
int socket(int domain, int type, int protocol);
domain: 指定通信协议族,如 AF_INET(IPv4)、AF_INET6(IPv6)、AF_UNIX(本地通信)、AF_PACKET(底层套接字,直接在链路层发送和接收原始数据包)。
type: 指定套接字类型,如 SOCK_STREAM(流式套接字,面向连接)或 SOCK_DGRAM(数据报套接字,无连接)、SOCK_RAW(原始套接字,允许直接访问下层协议)、SOCK_SEQPACKET(有序数据包套接字)。
protocol: 指定协议类型,通常使用 0 以选择默认协议。IPPROTO_TCP:指定使用 TCP 协议(通常与 SOCK_STREAM 搭配使用)。IPPROTO_UDP:指定使用 UDP 协议(通常与 SOCK_DGRAM 搭配使用)。IPPROTO_ICMP:指定使用 ICMP 协议(通常与 SOCK_RAW 搭配使用)。
返回值: 成功返回一个非负整数表示文件描述符(Socket Descriptor)。失败返回-1,并设置 error 变量表示错误类型。EACCES:权限不足,通常出现在尝试创建原始套接字时。EMFILE:当前进程已打开的文件描述符过多,超过了系统限制。ENFILE:系统级别的打开文件描述符数超过限制。EAFNOSUPPORT:指定的地址族不支持。EPROTONOSUPPORT:指定的协议不支持。EPROTOTYPE:指定的协议不匹配所选的套接字类型。
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
int sockfd;
// 创建一个 IPv4 的 TCP 套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
printf("Socket created successfully, sockfd: %d\n", sockfd);
// 关闭套接字
close(sockfd);
return 0;
}
bind()
将套接字绑定到特定的地址和端口。
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd: 由 socket() 返回的套接字描述符。
addr: 指向 sockaddr 结构体的指针,包含套接字的地址信息。
addrlen: sockaddr 结构体的大小。
返回值: 返回 0,表示绑定成功。失败返回 -1,并设置 errno 以指示具体的错误类型。EACCES:权限不足,通常在绑定到特定端口(如低于 1024 的端口)时发生。EADDRINUSE:指定的地址或端口已被占用。EBADF:sockfd 不是有效的文件描述符。EINVAL:sockfd 已经绑定了另一个地址,或地址不适用于套接字。ENOTSOCK:sockfd 并不是一个套接字描述符。EADDRNOTAVAIL:指定的地址在本地机器上不可用。
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
int sockfd;
struct sockaddr_in servaddr;
// 创建一个 IPv4 的 TCP 套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// 填充服务器地址结构体
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY; // 绑定到所有本地地址
servaddr.sin_port = htons(8080); // 绑定到端口 8080
// 绑定套接字到指定地址和端口
if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
perror("bind");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("Socket bound to port 8080\n");
// 关闭套接字
close(sockfd);
return 0;
}
listen()
将一个套接字标记为被动套接字,用于接收连接请求(通常在服务器端使用)。
int listen(int sockfd, int backlog);
sockfd: 套接字描述符。
backlog: 等待连接队列的最大长度。实际能接受的 backlog 值可能受到系统的 SOMAXCONN 限制(在大多数系统中 SOMAXCONN 的值为 128)。
返回值: 返回 0,表示监听操作成功。失败返回 -1,并设置 errno 以指示具体的错误类型。EBADF:sockfd 不是有效的文件描述符。ENOTSOCK:sockfd 不是一个套接字描述符。EOPNOTSUPP:该套接字不支持监听操作(例如,非流式套接字)。EADDRINUSE:该地址已经被绑定到另一个套接字,且不允许重用。
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
int sockfd;
struct sockaddr_in servaddr;
// 创建一个 IPv4 的 TCP 套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// 填充服务器地址结构体
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY; // 绑定到所有本地地址
servaddr.sin_port = htons(8080); // 绑定到端口 8080
// 绑定套接字到指定地址和端口
if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
perror("bind");
close(sockfd);
exit(EXIT_FAILURE);
}
// 将套接字设置为监听模式,等待连接请求
if (listen(sockfd, 10) == -1) {
perror("listen");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("Server is listening on port 8080...\n");
// 通常在这里会调用 accept() 以处理传入的连接请求
// 关闭套接字
close(sockfd);
return 0;
}
accept()
接受一个传入的连接请求,创建一个新的连接套接字(用于服务器端)。
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockfd: 监听套接字的描述符。
addr: 用于存储客户端地址信息的 sockaddr 结构体。
addrlen: 存储 sockaddr 结构体的大小。
返回值: 成功返回一个新的套接字文件描述符,用于与客户端进行通信。失败返回 -1,并设置 errno 以指示具体的错误类型。EBADF:sockfd 不是有效的文件描述符。EINVAL:sockfd 不是一个监听套接字,或者 addrlen 不正确。EINTR:系统调用被信号中断。ENOBUFS:系统没有足够的缓冲区来完成请求。ENOMEM:内存不足。
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int listenfd, connfd;
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddrlen;
char buffer[BUFFER_SIZE];
// 创建一个 IPv4 的 TCP 套接字
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd == -1) {
perror("socket");
exit(EXIT_FAILURE

最低0.47元/天 解锁文章
775

被折叠的 条评论
为什么被折叠?



