基于TCP协议的网络编程流程
服务器端:
1) socket(),创建套接字文件,用于连接
2) bind(), 绑定,把socket()函数返回的文件描述符和IP、端口号进行绑定;
3) listen(), (监听)将socket()返回的文件描述符的属性,由主动变为被动;
4) accept(), 阻塞函数,阻塞等待客户端的连接请求,如果有客户端连接,
则accept()函数返回,返回一个用于通信的套接字文件;
5) recv(), 接收客户端发来的数据; read()
6) send(), 发送数据;
7) close(), 关闭文件描述符;连接、通信
客户端:
1) socket(),创建套接字文件,既用于连接,也用于通信;
2) connect(); 用于发起连接请求;
3) send(), 发送数据;
4) recv(), 接收数据;
5) close(), 关闭文件描述符;
用到的API
1.int socket(int domain, int type, int protocol); domain:地址族 type:TCP协议 protocol:协议族
功能: 创建套接字文件
参数:
domain:协议族
AF_UNIX, AF_LOCAL 用于本地通信
AF_INET IPv4 Internet protocols ip
AF_INET6 IPv6 Internet protocols ipv6
type:协议类型
SOCK_STREAM TCP
SOCK_DGRAM UDP
protocol:
一般情况下写0
系统默认自动帮助匹配对应协议
传输层:IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP
网络层:htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL)
返回值:
成功: 返回一个文件描述符;
失败: -1
2. int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能: 绑定,将socket()返回值和IP/端口号进行绑定;
参数:
sockfd: 是socket()函数的返回值;
const struct sockaddr *addr:
struct sockaddr是结构体类型,是一个通用结构体;
struct sockaddr {
sa_family_t sa_family; // 2个字节typedef unsigned short int sa_family_t; //
char sa_data[14]; // 14字节
}
整个结构体大小为16个字节
******在填充的时候填充struct sockaddr_in ;
struct sockaddr_in {
unsigned short sin_family; //协议IPv4,2个字节
unsigned short sin_port; //端口号 ,2个字节
struct in_addr sin_addr;
struct in_addr {
__be32 s_addr; //IP地址,4个字节
};
/* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
//8个字节
};
addrlen:结构体的大小;
sizeof(serveraddr);
返回值:-1 失败
3.int listen(int sockfd, int backlog);
功能: 用于监听,将主动套接字变为被动套接字;
参数:
sockfd: socket()的返回值
backlog:客户端同时连接服务器的最大个数;(队列1:保存正在连接) (队列2,连接上的客户端)
返回值:失败 -1
4.int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
阻塞函数,阻塞等待客户端的连接请求,如果有客户端连接,则accept()函数返回,返回一个用于通信的套接字文件;
参数:
sockfd:同上
addr: 如果不需要关系具体是哪一个客户端,那么可以填NULL;
addrlen:如果不需要关系具体是哪一个客户端,那么可以填NULL;
返回值: 文件描述符;acceptfd;
5.ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能: 接收数据
参数:
sockfd: acceptfd ;
buf 存放位置
len 大小
flags 一般填0
6.其他API
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *strptr); 两个函数都是将主机点分十进制IP转化为网络字节序
char *inet_ntoa(stuct in_addr inaddr);将32位网络字节序二进制地址转换成点分十进制的字符串。
u_long htonl (u_long hostlong); 主机字节序到网络字节序
u_short htons (u_short short);主机字节序到网络字节序
u_long ntohl (u_long hostlong);网络字节序到主机字节序
u_short ntohs (u_short short);网络字节序到主机字节序
7.int connect(int sockfd, const struct sockaddr *addr,ocklen_t addrlen);
功能:用于连接服务器;
参数:sockfd:socket函数的返回值
addr: 填充的结构体是服务器端的;
addrlen:结构体的大小
返回值 -1 失败,正确 0
8. ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:发送数据
参数:基本同recv
flags 如果天0,相当于write();