Socket英文愿意是“插孔”或“插座”,作为BSD UNIX的进程通信机制后,取后一种意思,通常也被称为套接字。使用TCP/IP协议的应用程序通常采用的应用编程是使用UNIX BSD的套接字Socket,来实现网络进程之间的通信。
Socket用于描述IP地址和端口,是一个通信链的句柄,用来实现不同虚拟机或物理机之间的通信。应用程序通过Socket向网络发出请求或应答请求。网络中两个进程通过一个双向的通信连接实现数据的交换,建立网络通信连接至少需要一对Socket,连接的一端称为一个Socket。
具有唯一标识的网络进程可利用 Socket 进行通信,而 Socket 是在应用层和传输层之间的一个抽象层,Socket把TCP/IP层复杂的操作抽象为简单的接口供应用层调用,以实现进程在网络中的通信。TCP/IP协议存在于操作系统中,网络服务是通过操作系统提供的,因此在操作系统中增加支持TCP/IP的系统调用Socket。
在Linux系统中,一切皆文件,Socket也不例外,对socket的操作实际上也是对某种特殊文件的读写操作。只不过操作的文件在服务器和客户端各自拥有一个。
下图是最基本的socket 通信流程,也就是最初的网络I/O模型(阻塞I/0模型),注意这里展示的是TCP通信流程。
服务器端:
1.生成一个监听的socket,绑定IP地址和端口号
2.监听客户端的请求,并接受客户端的连接
客户端:
1.创建通信socket,
2.连接到服务器
客户端与服务器通信:
1.客户端连接成功向服务器发送连接状态信息
2.服务器端Accetp返回连接socket
3.客户端使用socket写入数据
4.服务器使用连接socket来接收数据
int socket(int domain, int type, int protocol)
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
将socket和对应的端口和地址进行绑定,一般用于绑定服务器的监听socket,以便能够让客户端连接到服务器对应的ip和端口。
struct sockaddr{
sa_family_t sa_family;
char sa_data[14];
};
int listen(int sockfd, int backlog);
服务器端使用listen接口来监听客户端的连接
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
该接口用于客户端连接服务器
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
主要用于服务器端接收客户端的连接,当客户端发起连接请求后,accept会返回当前连接客户端的socket信息。
参数同connect 接口
-返回值
成功,返回一个socketfd,这个socketfd记录了连接客户端的信息,服务器使用这个socket同客户端进行通信。
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
recv和recvfrom主要用于接收对等端发送的信息,接收的信息存储于buf参数中。
recvfrom与recv不同之处的主要是前者多了2个参数,src_addr和addrlen,从参数名字就知道这2个参数主要是用于表示该请求的发送者的地址信息,由于UDP通信一般不需要客户端先连接服务器,因此recvfrom通常用于UDP通信,recv用于TCP通信。
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
send/sendto主要用于发送消息给对等方,send主要用于TCP通信,sendto主要用于UDP通信。
MSG_DONTROUTE:告诉内核,目标主机在本地网络,不用查路由表
MSG_DONTWAIT:将单个I/O操作设置为非阻塞模式
MSG_OOB:指明发送的是带外信息
Linux C TCP编程(socket编程)