[(12条消息) 网络编程(4.7作业)(TCP/UDP源代码)_m0_37565374的博客-CSDN博客]:
功能:在内核空间中创建两个缓冲区:接收缓冲区,发送缓冲,用户空间可以接收到两块空间的文件描述符
原型:
#include /* See NOTES */
#include
int socket(int domain, int type, int protocol);
参数:
int domain:指定协议族(地址族)
Name | Purpose | Man page |
---|---|---|
AF_UNIX, AF_LOCAL | 局域网 | unix(7) |
AF_INET | ipv4 | ip(7) |
AF_INET6 | ipv6 | ipv6(7) |
int type:
SOCK_STREAM | 字节流式套接字:默认指定TCP协议 |
---|---|
SOCK_DGRAM | 数据报式套接字:默认指定UDP协议 |
SOCK_RAW | 原始套接字,协议需要在第三个参数指定; |
int protocol:指定协议; 默认协议填0;
返回值:
功能:将IP和端口绑定到套接字上
原型:
#include /* See NOTES */
#include
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
int sockfd:指定要绑定到哪个套接字上,填对应文件描述符;
struct sockaddr*addr:通用地址信息结构体,真实的地址信息结构体根据地址族指定;
指定需要绑定到套接字上的IP和端口
--AF_INET--man 7 ip----
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */ 必须填AF_INET;
in_port_t sin_port; /* port in network byte order */ 端口号的网络字节序,1024~49151
struct in_addr sin_addr; /* internet address */ 本机IP地址的网络字节序
终端输入:ifconfig查看本机IP
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
返回值:
功能:将套接字设置为被动监听状态,监听是否有客户端连接成功;
原型:
#include /* See NOTES */
#include
int listen(int sockfd, int backlog);
参数:
返回值:
功能:阻塞函数,从已完成连接的队列头中获取一个客户端信息,生成一个新的文件描述符
该文件描述符才是与客户端通信的文件描述符!!
原型:
#include /* See NOTES */
#include
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数:
int sockfd:被设置为被动监听状态的文件描述符;
struct sockaddr *addr:通用地址信息结构体,真实的地址信息结构体根据地址族指定;
存储连接成功的客户端的地址信息。如果不想获取,则填NULL;
socklen_t *addrlen:真实的地址信息结构体的大小,注意是指针类型,需要在外部定义普通变量,赋值后取地址;
如果第二个参数填NULL,则当前参数填NULL;
返回值:
功能:从指定的套接字文件描述符中,接收数据
原型:
#include
#include
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
参数:
int sockfd:指定要从哪个文件描述符中获取数据,填accept函数获取到的新的文件描述符;
void *buf:该指针指向的内存空间中存储获取到的数据,可以是任意类型数据;
size_t len:指定要接收的数据大小,以字节为单位;
int flags:
0:阻塞方式接收,当没有数据的时候阻塞;
MSG_DONTWAIT:非阻塞;
返回值:
功能:通过套接字文件描述符,向指定套接字发送数据;
原型:
#include
#include
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
参数:
int sockfd:指定要向哪个文件描述符发送数据,填accept函数获取到的新的文件描述符;
void *buf:指定要发送的数据首地址,可以是任意类型数据;
size_t len:指定要发送的数据大小,以字节为单位;
int flags:
0:阻塞方式发送,当数据满的时候阻塞;
MSG_DONTWAIT:非阻塞;
返回值:
功能:通过服务器的IP和端口,连接指定服务器;
原型:
#include /* See NOTES */
#include
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
int sockfd:指定要将哪个套接字与服务器连接;
struct sockaddr *addr:通用地址信息结构体,真实的地址信息结构体根据地址族指定;
指定要连接的服务器所绑定的IP和端口;
socklen_t addrlen:真实的地址信息结构体的大小:sizeof(struct sockaddr_in);
返回值:
bind报错:
功能:从指定套接字中接收数据,同时可以接收到该数据包从哪个发送方发送过来的
原型:
#include
#include
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(sockfd, buf, len, flags); 相当于 recvfrom(sockfd, buf, len, flags, NULL, NULL);
功能:将数据发送到指定的套接字中,需要指定发给谁,即指定好接收方的地址信息结构体
原型:
#include
#include
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);
参数:
int sockfd:指定要向哪个文件描述符发送数据,填accept函数获取到的新的文件描述符;
void *buf:指定要发送的数据首地址,可以是任意类型数据;
size_t len:指定要发送的数据大小,以字节为单位;
int flags:
const struct sockaddr *dest_addr:通用地址信息结构体,真实的地址信息结构体跟着地址族来定
需要填充接收方的地址信息结构体,指定数据要发给谁;
socklen_t addrlen:真实的地址信息结构体的大小:sizeof(struct sockaddr_in);
返回值:
send(sockfd, buf, len, flags); 相当于sendto(sockfd, buf, len, flags, NULL, 0);
udp中可以使用connect函数,但是不会产生连接
TCP中的connect函数会产生三次握手,将client和server连接。
UDP中的connect函数,仅仅是将对端的IP和端口记录到内核套接字空间中,此时是udp只能与记录的对端进行通信。
TCP中的connect函数只能被调用一次。
UDP中的connect函数可以被调用多次,刷新内核中对端的IP和端口,
如果想要清空内核中对端的地址信息,则将sin_family
成员设置为AF_UNSPEC,调用connect函数即可。
当udp采用connect函数的方式收发报文后,可以调用send write recv read函数。也可以使用sendto recvfrom.但是需要使用以下形式
sendto(sfd, buf, sizeof(buf), 0, NULL, 0);
recvfrom(sfd, buf, sizeof(buf), 0, NULL, NULL);
udp中的connect函数的优点:
提升传输效率
增加传输时候的稳定性
sendto(sfd, buf, sizeof(buf), 0, NULL, 0);
recvfrom(sfd, buf, sizeof(buf), 0, NULL, NULL);
udp中的connect函数的优点:
提升传输效率
增加传输时候的稳定性