1.创建Socket文件描述符
在TCP与UDP通信中,首先要创建一个Socket文件描述符,本质上是一个网络文件
函数原型
#include<sys/types.h>
#include<sys/socket.h>
int socket(int domain,int type,int protocol)
{
}
功能:打开一个网络通讯端口,返回一个文件描述符,如果失败返回-1
参数分析:
1.domain:协议域,如AF_INET(IPV4),AF_INET6(IPV6),AF_LOCAL(Unix域套接字)
2.type:套接字类型,如SOCK_STREAM(字节流,TCP),SOCK_DGRAM(数据报,UDP)
3.protocol:协议类别,通常设置为0,自动推导出对应的协议,如TCP/UDP
2.绑定bind端口号(服务器)
在服务器端,必须绑定一个IP地址和端口号,以便客户端可以与服务器建立通信,bind()函数用于将套接字与IP和端口号绑定
函数原型
int bind(int sockfd,const struct sockaddr*addr,socklen_t addrlen)
{
}
功能:将指定IP和端口号绑定到套接字,使之监听指定地址
参数分析:
1.sockfd:套接字文件描述符
2.addr:存储地址和端口号的结构体指针
3.addrlen:地址结构体的长度
3.开始监听Socket(TCP服务器)
在服务器,使用listen()函数使套接字进入监听状态,准备接受连接请求
函数原型
int listen(int sockfd,int backlog)
{
}
功能:让服务器套接字进入监听状态,准备接收客户端连接
参数
1.socket:监听套接字描述符
2.backlog:全连接队列的最大长度,用于处理多个客户端连接请求
4.接收连接请求(TCP服务器)
服务器使用accept()从连接队列提取下一个连接请求,并返回新的套接字用于与客户端通信
函数原型
int accept(int sockfd,struct sockaddr *addr,socklen_t addrlen)
{
}
功能:获取一个已完成的连接请求,并返回新的套接字用于客户端通信
参数分析:
1.socket:监听套接字
2.address:存储客户端的地址信息
3.address_len:地址结构的长度
5.建立连接(TCP客户端)
客户端通过connect()向服务器发起连接请求
函数原型
int connect(int sockfd,const struct sockaddr*addr,socklen_t addrlen)
{
}
功能:TCP客户端使用该函数建立与服务器的连接
参数分析:
1.sockfd:用于通信的套接字文件描述符
2.addr:服务器的地址
3.addrlen:地址长度
6.设置套接字选项
通过setsockopt()可以设置套接字的各种属性,例如端口重用等高阶功能
函数原型:
int setsockopt(int sockfd,int level,int optname,const void *optval,socken_t optlen)
{
}
功能:设置套接字的选项,如端口重用等
参数分析:
1.sockfd:套接字文件描述符
2.level:选项的层次(SOL——SOCKET,IPPROTO_TCP等)
3.optname:选项名
4.optval:指向设置值的指针
5.optlen:设置值的长度
7.地址转换函数
字符串IP转整数IP
in_addr_t inet_addr(const char *strptr);
int inet_pton(int family, const char *strptr, void *addrptr);
整数IP转字符串IP
char *inet_ntoa(struct in_addr addr);
const char *inet_ntop(int family, const void *src, char *dest, size_t len);
8.。数据传输函数
sendto()(UCP)用于在UDP协议下发送数据
函数原型
ssize_t sendto(int sockfd,const void *buf,size_t len,int flags,const struct sockaddr*dest_addr,socklen_t addrlen)
{
}
功能:发送数据到指定地址
参数分析:
1.sockfd:套接字文件描述符
2.buf:要发送的数据
3.len:数据长度
recvfrom()(UCP)
函数原型
ssize_t recvfrom(int sockfd,void *buf,size_t len,int flags,struct sockaddr*src_addr,socklen_t*addrlen)
{
}
功能:接收数据
参数分析
1.sockfd:套接字文件描述符
2.buf:存放接收数据的缓冲区
send()和recv()(TCP)
send()用于在TCP协议下发送数据
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
recv()用于接收TCP协议下的数据
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
9.实际使用中的注意事项
INADDR_ANY
在服务器端,INADDR_ANY(0.0.0.0)可以让服务器监听所有可用的网络接口,而不必指定具体的IP地址,这种方式提高了代码的可移植性
local.sin_addr.s_addr = INADDR_ANY;
客户端不需要手动绑定端口,操作系统会自动选择一个可用的端口,除非明确需要使用固定的端口,否则不建议手动绑定
Listening Socket 与Connected Socket
Listening Socke:服务器使用它来监听连接请求。它在整个服务器生命周期内存在
Connected Socket:服务器接收连接请求后,用于与客户端通信的套接字。每个客户端有一个独立的连接套接字
10.TCP通信流程
1.服务器初始化:调用socket()创建套接字,调用bind()绑定地址和端口,调用listen()进入监听状态
2.客户端连接:客户端通过socket()创建套接字,使用connect()发起连接请求
3.三次握手:TCP客户端与服务器通过三次握手建立连接
4.数据传输:连接建立后,双方可以通过send()和recv()进行数据传输
5.断开连接:通过四次挥手,客户端与服务器断开连接
11.TCP和UDP
TCP:可靠的连接,字节流传输,保证数据顺序
UDP:不可靠传输,数据报传输,适用于实时通信
12.popen()和pclose()
popen()创建一个管道用于和子进程通信:来实现命令行通信
FILE *popen(const char *command, const char *type);
pclose()关闭通过popen()打开的文件指针
int pclose(FILE *stream);
使用场景:Udpcommand
Socket 编程是网络编程的基础,通过 Socket API,开发者可以实现 TCP 和 UDP 通信。了解每个函数的作用、参数和使用场景,可以帮助开发者在构建高效、稳定的网络应用时得心应手