套接字(socket)
什么是套接字
套接字是一种通信机制
通过套接字,可实现本机内的通信、也可以实现跨网络的通信。使用套接字实现本地通信(本机内的服务器和客户端)
实例:server1.c
client1.c文件系统套接字服务器客户端开发步骤
文件系统套接字,用于本机内通信
1) 服务器端
(1) 删除以前的文件系统套接字所对应的文件
(2) 创建一个文件系统套接字
(3) 设置服务器地址
(4) 绑定该套接字,使得该套接字和对应的系统套接字文件关联起来。
(5) 创建套接字队列, 保存进入该服务器的客户端请求
(6) 循环处理客户端请求
使用accept等待并接收客户端请求
收到客户端请求后,accept返回一个新的socket(表示该客户端连接)
使用这个新的socket,对客户端进行“读写“
处理完毕后,关闭这个新的socket2) 客户端
(1) 创建一个套接字
(2) 设置服务器地址
(3) 使用该socket和服务器地址连接服务器(connect)
(4) 使用该socket发送和接受数据。
(5) 关闭该socket相关系统调用
1)创建套接字
socket
原型:int socket(int domain, int type, int protocol);
参数:domain, 表示套接字的域,相当于套接字的类型
常用的域有:AF_UNIX , 文件系统套接字,用于在本机的文件系统内通信
AF_INET, UNIX网络套接字,用于网路通信。
type, 表示该套接字的特性
文件系统套接字,一般使用SOCK_STREAM
UNIX网络套接字,可使用:
SOCK_STREAM, 使用TCP通信
SOCK_DGRAM, 使用UDP通信补充:SOCK_STREAM, 是有序、可靠、面向连接的通信, 对于UNIX网络套接字,通过TCP实现 SOCK_DGRAM, 即数据报服务,不保证按序到达, 对于UNIX网络套接字,通过UDP实现 protocol,具体使用的协议。 一般取0,即表示使用默认的协议。
2) 套接字地址
文件系统套接字的地址:
struct sockaddr_un {
sa_family_t sun_family; //即取AF_UNIX
char sun_path[UNIX_PATH_MAX]; //路径名
}
UNIX网络套接字:
struct sockaddr_in {
short int sin_family; //取 AF_INET
unsigned short int sin_port; //端口号
struct in_addr sin_addr; // ip地址
}
补充:
struct in_addr {
unsigned long int s_addr; //4字节的IP地址
//例:addr.s_addr = inet_addr("192.168.168.110")
}
注意:相关的系统调用中,使用的地址又是struct sockaddr类型,
所以需要进行类型转换,否则将出现警告。
2)绑定套接字
对于文件系统套接字,绑定该套接字后,
使得该套接字和对应的系统套接字文件关联起来
对于UNIX网络套接字,绑定该套接字后,使得该套接字和一个端口号关联起来
bind
原型:int bind (int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);
返回值:成功,返回0
失败,返回-1
注意:绑定文件系统套接字时,地址中sun_path如果不指定绝对路径,则表示使用当前路径。
如果在当前路径无相关权限,则可能导致bind失败。
解决办法:指定一个具有权限的路径即可,比如/tmp/...
3) 创建套接字队列
listen
原型:int listen (int sockfd, int backlog);
功能: 创建一个队列,用来保存访问该服务器套接字的请求。
参数2表示同时最多能接受多少个客户端 请求,一般取5,即该队列中最多可排5个请求。
返回值:成功,返回0
失败, 返回-1
4)接受客户端请求
accept
原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:等待并接受客户端的请求。
如果没有客户端发起请求,则阻塞。
如果已有多个请求,则在该套接字的队列中取出第一个请求。
参数:sockfd, 服务器套接字。
addr, 所接收到的客户端地址
注意:如果不关心所接受的客户端的地址,则param2和param3都可以为0
返回值:成功,则返回一个新的套接字,以表示与该客户端的连接。
直接使用该套接字,就可以对客户端进行读写。
失败:返回-1
注意:参数3必须要初始化为对应地址的长度!
5)向服务器发送连接请求
connect
原型:int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
参数:sockfd, 表示连接服务器的套接字
serv_addr, 服务器的地址
addrlen, 服务器地址的长度
返回值:成功, 0
失败, -1
6) 关闭套接字
close(socket_fd);
关闭对应的连接。
// 补充:
当客户端关闭后,
服务器端可以对该客户端进行读read,不阻塞返回0
但不能对该客户端进行write操作,否则异常退出