TCP网络编程流程图
下面我们会一次介绍每一个函数
socket()函数
作用
它用于创建一个网络通信端点(打开一个网络通信)
函数包含的头文件和函数原型
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
参数:
domain:用于指定一个通信域,这将选择将用于通信的协议族。具体可用的协议族如下
Name Purpose Man page
AF_UNIX Local communication unix(7)
AF_LOCAL Synonym for AF_UNIX
AF_INET IPv4 Internet protocols ip(7)
AF_AX25 Amateur radio AX.25 protocol ax25(4)
AF_IPX IPX - Novell protocols
AF_APPLETALK AppleTalk ddp(7)
AF_X25 ITU-T X.25 / ISO-8208 protocol x25(7)
AF_INET6 IPv6 Internet protocols ipv6(7)
AF_DECnet DECet protocol sockets
AF_KEY Key management protocol, originally de‐
veloped for usage with IPsec
AF_NETLINK Kernel user interface device netlink(7)
AF_PACKET Low-level packet interface packet(7)
AF_RDS Reliable Datagram Sockets (RDS) protocol rds(7)
rds-rdma(7)
AF_PPPOX Generic PPP transport layer, for setting
up L2 tunnels (L2TP and PPPoE)
AF_LLC Logical link control (IEEE 802.2 LLC)
protocol
AF_IB InfiniBand native addressing
AF_MPLS Multiprotocol Label Switching
AF_CAN Controller Area Network automotive bus
protocol
AF_TIPC TIPC, "cluster domain sockets" protocol
AF_BLUETOOTH Bluetooth low-level socket protocol
AF_ALG Interface to kernel crypto API
AF_VSOCK VSOCK (originally "VMWare VSockets") vsock(7)
protocol for hypervisor-guest communica‐
tion
AF_KCM KCM (kernel connection multiplexor) in‐
terface
AF_XDP XDP (express data path) interface
type:指定套接字的类型,当前支持的类型有
SOCK_STREAM Provides sequenced, reliable, two-way, connection-
based byte streams. An out-of-band data transmission
mechanism may be supported.(tcp)
SOCK_DGRAM Supports datagrams (connectionless, unreliable mes‐
sages of a fixed maximum length).(udp)
SOCK_SEQPACKET Provides a sequenced, reliable, two-way connection-
based data transmission path for datagrams of fixed
maximum length; a consumer is required to read an en‐
tire packet with each input system call.
SOCK_RAW Provides raw network protocol access.
SOCK_RDM Provides a reliable datagram layer that does not guar‐
antee ordering.
SOCK_PACKET Obsolete and should not be used in new programs; see
packet(7).
protocol:通常设置为0,
返回值:
成功返回socket描述符。
失败返回-1,并且会设置 errno 变量以指示错误类型。
bind()函数
作用
用于将一个 IP 地址或端口号与一个套接字进行绑定(将套接字与地址进行关联)。主要是使用到服务器,一般来讲,会将一个服务器的套接字绑定到一个众所周知的地址。
函数包含的头文件和函数原型
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
参数
sockfd:socket()函数得到的socket描述符
addr:要的是一个地址,
struct sockaddr结构体如下图
addrlen:最后一个参数是这个结构体的长度
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
第二个成员 sa_data 是一个 char 类型数组,一共 14 个字节,在这 14 个字节中就包括了 IP 地址、端口 号等信息,这个结构对用户并不友好,它把这些信息都封装在了 sa_data 数组中,这样使得用户是无法对 sa_data 数组进行赋值。一般我们在使用的时候都会使用 struct sockaddr_in 结构体,sockaddr_in 和 sockaddr 是并列的结构(占 用的空间是一样的),指向 sockaddr_in 的结构体的指针也可以指向 sockadd 的结构体,并代替它,而且 sockaddr_in 结构对用户将更加友好,在使用的时候进行类型转换就可以了。该结构体内容如下所示:
struct sockaddr_in {
sa_family_t sin_family; /* 协议族 */
in_port_t sin_port; /* 端口号 */
struct in_addr sin_addr; /* IP 地址 ,需要的是32位的IP地址,不是10进制的点分形式的地址*/
unsigned char sin_zero[8];//保留未用
};
这里的in_addr又是一个结构体里面就只填一个ip地址,这里要强调的是需要32位形式的地址,并且端口号和ip地址都需要将本地字节序转换网络字节序。十进制点分形式的IP地址转换位32位形式的IP地址稍后介绍。
返回值
成功返回0
失败返回-1,并且会设置 errno 变量以指示错误类型。
listen()函数
作用
listen()函数只能在服务器进程中使用,让服务器进程进入监听状态,等待客户端的连接请求,listen()函 数在一般在 bind()函数之后调用,在 accept()函数之前调用。
函数包含的头文件和函数原型
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
参数
sockfd:socket()函数得到的socket描述符。
backlog: 用来描述 sockfd 的等待连接队列能够达到的最大值。
返回值
成功返回0
失败返回-1,并且会设置 errno 变量以指示错误类型。
accept()函数
作用
服务器调用 listen()函数之后,就会进入到监听状态,等待客户端的连接请求,使用 accept()函数获取客 户端的连接请求并建立连接。accept()函数通常只用于服务器应用程序中,如果调用 accept()函数时,并没有客户端请求连接(等待连 接队列中也没有等待连接的请求),此时 accept()会进入阻塞状态,直到有客户端连接请求到达为止。当有 客户端连接请求到达时,accept()函数与远程客户端之间建立连接,accept()函数返回一个新的套接字。这个 套接字与 socket()函数返回的套接字并不同,socket()函数返回的是服务器的套接字(以服务器为例),而 accept()函数返回的套接字连接到调用 connect()的客户端,服务器通过该套接字与客户端进行数据交互,譬 如向客户端发送数据、或从客户端接收数据。
函数包含的头文件和函数原型
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数
sockfd:socket()函数得到的socket描述符。
addr: 是一个传出参数,只需声明即可,参数 addr 用来返回已连接的客户端的 IP 地址与端口号等这些信息。
addrlen: 应设置为 addr 所指向的对象的字节长度,如果我们对客户端的 IP 地址与端口号这些信息不感兴趣, 可以把 arrd 和 addrlen 均置为空指针 NULL。
返回值
成功返回一个与客户端建立连接的新的socket描述符。
失败返回-1,并且会设置 errno 变量以指示错误类型。
connect()函数
作用
该函数用于客户端应用程序中,客户端调用 connect()函数将套接字 sockfd 与远程服务器进行连接。
函数包含的头文件和函数原型
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数
sockfd:socket()函数得到的socket描述符。
其他参数设置参见bind()函数
返回值
成功返回0
失败返回-1,并且会设置 errno 变量以指示错误类型。
ip地址格式转换函数
inet_addr()函数
作用:将点分十进制表示的字符串形式转换成二进制 Ipv4 或 Ipv6 地址。
函数原型:in_addr_t inet_addr(const char *cp);
cp:点分形式的IP地址,
特点:它只适用于IPV4
此函数不能用于255.255.255.255的转换
自带网络字节序
inet_pton()函数
作用:inet_pton()函数将点分十进制表示的字符串形式转换成二进制 Ipv4 或 Ipv6 地址。
函数原型:int inet_pton(int af, const char *src, void *dst);
参数:
af:协议族
src:源:表示点分形式的
dst:转换后保存的地址
inet_ntop()函数
作用:inet_pton()函数相反
函数原型:const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
参数:
af:协议族
src:源:表示二进制的ip
dst:转换后保存的地址
网络字节序与本地字节序的转换
本地字节序到网络字节序
u_long htonl(u_long hostlong);
u_long htons (u_short short);
网络字节序到本地字节序
u_long ntohl(u_long hostlong);
u_long ntohs (u_short short);