简单的客户端C与服务器S通信
服务端S使用函数及其顺序:
套接字文件描述符状态
socket() 阻塞
bind() 阻塞
listen() 监听
accept() 监听/阻塞,(等待客户端的connect申请,收到connect申请后:ESTABLISHED状态 )
recv() ESTABLISHED
close() 关闭
客户端C使用函数及其顺序:
套接字文件描述符状态
socket() 阻塞
connet() 阻塞,三次握手后:ESTABLISHED状态
send() ESTABLISHED
close() 关闭
函数的作用:
socket 返回的套接字文件描述符A默认为阻塞,但可通过setsockopt函数设置该文件描述符的属性
bind 使套接字A绑定IP和端口,S要绑定本机IP和端口,C要绑定S的IP和端口
listen 使A进入监听状态
accept S处于监听的A等待C的链接申请,当C通过connect函数发来的申请,S与C进行三次握,握手成功返回一个新的文件描述符B用 于与C通信同时状态为ESTABLISHED
connect C向S发送通信申请,三次握手成功后,文件描述符为ESTABLISHED
send C用于向S发送数据
recv S用于接收C发过来的数据
函数的参数:
协议族 套接字类型
int socket(int domain, int type, int protocol)
PF_INET SOCK_STREAM
PF_UNIX SOCK_DGRAM
PF_NS SOCK_RAW
PF_IMPLINK
<sys/types.h>
<sys/socket.h>
返回:成功:套接字文件描述符
失败:-1
相关的数据结构:
int bind (int sockfd, struct sockaddr *addr, int addrlen)
由socket返回 地址属性 指定地址属性长度
返回:0或-1
通用地址结构
struct sockaddr
{
u_short sa_family; //协议族
char sa_data[14]; //14字节协议地址
}
intetnet协议地址结构
struct sockaddr_in
{
u_short sin_family; //协议族
u_short sin_port; //端口
struct in_addr sin_addr; //IPV4地址
char sin_zero[8]; //
}
struct in_addr
{
in_addr_t s_addr; //u32 IP地址
}
在使用bind是必须初始化以上数据结构
int listen(int sockfd, int backlog)
监听连接的套接字 指定连接的队列长度(连接数)
<sys/types.h>
<sys/socket.h>
由socket返回 发送缓冲首地址 发送字节数 发送方式
=0时相当于write函数
<sys/socket.h>
返回:实际发送字节数 或-1
ssize_t recv(int sockfd, const void *buf, size_t len, int flags)
参数同send
其他函数:
memset() 和 bzero()用于清空 地址属性机构体
sendto()
recvfrom()