概念
背景:
- 在网络中,一个进程的唯一标识 = IP + port + 协议。进程有了唯一标识,就可以进行网络通信。
- 有了进程的唯一标识,两个进程想要进行网络通信,那就需要 socket。
从上述描述,就知道 socket 其实是用于网络通信。下面看看正式的定义。
socket 是在应用层和传输层之间的抽象层,并将TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用(即API),程序员通过调用 API 来实现进程在网络中通信
socket理解:socket 起源于 Unix,而在万物皆是文件的 Unix 中,socket 也可以看成一个文件,服务器和客户端各自维护一个 socket “文件”,在建立连接打开后,可以向自己文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件。
下图展示的是服务器端和客户端“维护”一个 socket “文件”大致的过程:
使用 socket 的面向连接的通信模式socket API 解析
1)服务端使用的函数,其中 accept() 是最重要的一个函数
// 功能:将socket描述符与地址相关联,即给一个套接字赋给一个本地地址
// 返回:0/-1
int bind(int sockfd, const struct sockaddr *addr, socklen_t len);
// 功能:服务器调用此函数来宣告它愿意接收连接请求。一旦队列满,系统就会拒绝多余的连接请求
// 返回:0/-1
// 参数:backlog -- 提示系统,该socket可以排队的最大连接个数
int listen(int sockfd, int backlog);
// 功能:服务器使用该函数获得连接请求并与client建立连接
// 返回:-1 或 socketfd(该fd连接到调用connect函数的client,可理解一个连接)
// 参数:addr -- 用于存放client地址的缓冲区
// len -- 缓冲区大小
int accept(int sockfd, struct sockaddr *restrict addr,
socklen_t *restrict len);
2)客户端使用的函数
// 功能:client 与远程服务器建立连接
// 返回:0/-1
// 参数:addr -- 远程服务器地址
// sockfd -- 如果成功,它就是与server建立连接的socket描述符
int connect(int sockfd, const struct sockaddr *addr,
socklen_t len);
3)数据传输的函数
//****************************TCP****************************
// 功能:发送数据。
// 返回:发送成功的字节数。当函数成功返回,表示数据正确地发送到网络驱动程序上
// 参数:buf -- 存放要发送的数据
// nbytes -- buf的大小
ssize_t send(int sockfd, const void *buf,
size_t nbytes, int flag);
// 功能:接收数据
// 返回:成功接收到的数据的字节数。
// 参数:buf -- 存放接收到的数据
// nbytes -- buf的大小
ssize_t recv(int sockfd, void *buf, size_t nbytes, int flag);
//****************************UDP****************************
// 功能:UDP中的发送数据
// 参数:destaddr -- server 地址,因为UDP数据传输前不需要建立连接
ssize_t sendto(int sockfd, const void *buf, size_t nbytes,
int flags, const struct sockaddr *destaddr,
socklen_t destlen);
// 功能:接收数据
ssize_t recvfrom(int sockfd, void *restrict buf,
size_t nbytes, int flags,
struct sockaddr *restrict destaddr,
socklen_t destlen);
4)开启和关闭 socket 的函数
// 功能:创建一个socketfd
// 返回:一个socketfd
// 参数:domain -- 地址族,即是ipv4还是ipv6
// type -- socket类型
// protocol -- 协议,常用的协议有,IPPROTO_TCP、IPPTOTO_UDP等
int socket(int domain, int type, int protocol);
// 功能:关闭socket
int close(int sockfd);
// 功能:关闭socket传输,并不是关闭socket
int shutdown(int sockfd, int how);
socket编程示例:基于 TCP
介绍:Linux socket 编程实例:server对client每个连接发送一个 hello 后关闭。(只写重点)
1)服务器端代码
#include <sys/socket.h>
int main(int argc, char** argv){
int serverFd;
// 1.创建socket
if((serverFd = socket(AF_INET,SOCK_STREAN,0)<0){
print("create socket error\n");
exit(1);
}
// 省略设置参数
// 2.socketFd与地址绑定
if(bind(serverFd, &serverAddr, sizeof(serverAddr))<0){
print("bind socket error\n");
exit(1);
}
// 3.设置监听
listen(serverFd, LENGTH_OF_LISTEN_QUEUE);
while(true){
// 4.等待连接请求并建立连接
clientFd = accept(serverFd, NULL, NULL);
// 5.发送hello数据
send(clientFd, buf, BUFFER_SIZE, 0);
// 6.关闭连接
close(clientFd);
}
}
2)客户端代码
int main(int argc, char** argv)
{
// 1.创建socketFd
int clientFd = socket(AF_INET,SOCK_STREAN,0);
// 2.socketFd与本地地址绑定
bind(clientFd, &clientAddr, sizeof(clientAddr));
// 3.发送连接请求
connect(clientFd, &serverAddr, sizeof(serverAddr));
// 4.接收数据
int length = recv(clientFd, buf, BUFFER_SIZE);
print(buf);
}
参考文献
[1] 简单理解Socket - 谦行 - 博客园
[2] UNIX环境高级编程-网络IPC:套接字
网友评论