Socket 网络编程
文章目录
- Socket操作的常用系统调用
- 基于TCP的Socket程序流程
- Socket网络函数
- socket函数
- bind函数
- listen函数
- connect函数
- accept函数
- send函数和recv函数
Socket操作的常用系统调用
socket( ) | 建立Socket端点,获得Socket描述符 |
---|---|
bind( ) | Server绑定Socket地址(IP地址+端口号) |
listen( ) | Server等待Client连接 |
connect( ) | Client连接到Server |
accept( ) | Server获得连接请求的Client的Socket地址 |
send( ) / recv( ) | 在已建立的连接上发送 / 接收数据(TCP方式) |
sendto( ) / recvfrom( ) | 无需连接,直接发送 / 接收数据(UDP方式) |
close( ) | 关闭 Socket(双向/单向) |
基于TCP的Socket程序流程
利用Socket方式进行数据通信与传输,步骤如下:
- 创建服务端 socket,绑定建立连接的端口
- 服务端程序在一个端口调用 listen 及 accept 后,处于阻塞状态,等待客户机的连接
- 创建客户端 socket 对象
- 客户端指定主机名称或 IP 地址、连接端口号
- 客户机通过 connect 发起连接请求
- 建立连接
- 利用 send (sendto) 和 recv (recvfrom) 进行数据传输
- 关闭 socket
Socket网络函数
从上面的Socket程序流程图可以看见使用了很多函数,接下来详细讲解一下各个函数
socket函数
为了执行网络输入输出,一个进程必须做的第一件事就是调用 socket()
函数获得一个套接字描述符
socket()
函数原型为:
int socket(int family, int type, int protocol);
family
:指定使用协议簇AF_INET
: IPV4协议AF_INET6
:IPV6协议
type
:指定使用的套接字类型SOCK_STREAM
:字节流套接字SOCK_DGRAM
:数据报套接字SOCK_RAW
:原始套接字
protocol
:0(原始套接字除外)
函数返回值:成功返回非负套接字描述符;失败返回 -1
bind函数
bind()
函数为套接字描述符分配一个本地 IP 地址和一个端口号,将 IP 地址和端口号与套接字描述符绑定在一起
bind()
函数原型为:
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
sockfd
:套接字描述符my_addr
:指向本地 IP 地址结构的指针addrlen
:IP 地址的长度
函数返回值:成功返回 0
;失败返回 -1
listen函数
listen()
函数仅被 TCP 服务器调用,它的作用是将用 socket 创建的主动套接口转换成被动套接口,并等待来自客户端的连接请求
listen()
函数原型为:
int listen(int sockfd, int backlog);
sockfd
:socket 函数经绑定 bind 后的套接字描述符backlog
:设置可连接客户端的最大连接个数,默认值 20
函数返回值:成功返回 0
;失败返回 -1
connect函数
当客户端用 socket 建立了套接口后,可以调用 connect()
函数为这个套接字指明远程服务器的地址,以进行连接
connect()
函数原型为:
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
sockfd
:套接字描述符serv_addr
:指向服务器的 IP 地址结构的指针addrlen
:IP 地址的长度
函数返回值:成功返回 0
;失败返回 -1
accept函数
accept()
函数与 bind、listen 函数一样,是应用于 TCP 连接的服务端程序的函数
accept()
函数调用后,服务端程序一直会处于阻塞状态,等待来自客户端的连接请求
accept()
函数原型为:
int accept(int sockfd, struct sockaddr *cli_addr, socklen_t *addrlen);
sockfd
:socket 函数经 listen 后的套接字描述符cli_addr
:客户端套接字地址结构addrlen
:指向存有 addr 地址长度的整型数
函数返回值:若接收到客户端的连接请求,则返回非负套接字描述符;失败返回 -1
【注意】accept()
函数返回一个全新的套接字描述符
- 原来的套接字描述符继续侦听指定的端口
- 新的套接字则用于发送或接受数据
send函数和recv函数
send()
函数原型为:
int send(int sockfd, const void *msg, int len, int flags);
sockfd
:套接字描述符msg
:发送的数据的指针len
:发送数据的长度flags
:0
recv()
函数原型为:
int recv(int sockfd, void *buf, int len, unsigned int flags);
sockfd
:套接字描述符buf
:存放接收数据的缓冲区len
:接收数据的长度flags
:0
函数返回值:发送的字节数 / 接受数据的字节数