C++ 网络编程
C++ 网络编程
1. socket概念
socket是一种进程通信机制,被称为是套接字,引入一个标准名字空间进行进程之间的通信。
socket相当于是在传输层协议TCP/UDP之上的一层抽象层级更高的协议,方便应用程序进行使用。
socket主要使用在客户/服务器模型而设计的,针对客户和服务器程序需要提供不同的socket系统调用,运行在
客户端的被称为是clientSocket
,运行在服务器端的是serverSocket
套接字之间的连接主要分为三个步骤
- 服务器监听:服务器端套接字不定位具体的客户端套接字,而是处于等待的状态,实时监控网络状态
- 客户端请求:是指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。
为此客户端的套接字必须描述其要连接的服务器的套接字,指出服务器套接字的地址和端口号,然后
提出连接请求 - 连接确认:是指当服务器套接字监听到或者说接收到客户端套接字的连接请求,就响应客户端
套接字的请求,建立一个新的进程,把服务器套接字的描述发送给客户端,一旦客户端确认了次描述
连接就建立完成。
2. socket 函数
函数原型
1 |
|
domain
type
return
返回的是套接字的文件描述符,当无法创建的时候,返回-1
protocol 一般情况下都只能设置为0
对于socket地址结构体为sockaddr_in
sockaddr_in
的结构如下:
1 | struct sockaddr_in |
__SOCKADDR_COMMON
其实就是sin_family
表示其是地址族。
in_port_t
表示是端口号
in_addr
中是ip地址
1 | typedef uint32_t in_addr_t; |
对于in_addr的取值一般使用INADDR_ANY表示对所有地址都开放。
3. 网络序列和主机序列的转换
htonl
将无符号的主机长整数从主机字节序转换为网络字节序host to net long
htons
将无符号的主机短整型从主机字节序转换为网络字节序 host to net short
ntohl
从网络长到主机长
ntohs
从网络短到主机短
2. echo 服务器实现
2.1 server
对于server主要分为个部分
- 创建套接字
1 | sockaddr_in server_addr; |
- 配置套接字
1 | server_addr.sin_family = AF_INET; // 使用ipv4协议 |
- 绑定,将本地地址给套接字的文件描述符
1 | int bind(int socket, const struct sockaddr *address,socklen_t address_len); |
socket
: socket
的文件描述符
address
:sockaddr
类型的地址
address_len
:sockaddr
的长度
1 | if (bind(serverfd, (sockaddr*)&server_addr, sizeof(server_addr))== -1) { |
- 监听端口
监听某个套接字同时限制连接的数目。
1 | if (listen(serverfd, MAXLINK) == -1) { |
- 循环处理,进行处理
1 | int accept(int socket, struct sockaddr *restrict address,socklen_t *restrict address_len); |
接收来自套接字的一个新的连接,address
中存储的是连接的sockaddr
返回地址,address_len
输入提供的返回地址的长度。
1 | ssize_t recv(int socket, void *buffer, size_t length, int flags); |
从套接字中获取数据,flag设置为0即可
1 | ssize_t send(int socket, const void *buffer, size_t length, int flags); |
发送数据
1 | while (1) |
2.2 clinet
client的逻辑
- 创建套接字
1 | int clientfd = socket(AF_INET, SOCK_STREAM, 0); |
-
连接套接字
将客户端的套接字和服务器端的套接字进行相连
对于客户端连接的时候需要将字符串形式的ip地址转换为网络地址类,函数原型如下
1
int inet_pton(int af, const char *restrict src, void *restrict dst);
af
: 只能为ipv4或者ipv6,即AF_INET
/AF_INET6
src
: 服务器的ip地址dst
: 套接字的网络地址1
int connect(int socket, const struct sockaddr *address, socklen_t address_len)
socket
:套接字的文件描述符
address
:分支的地址
address_len
: 地址的大小
1 | if (connect(clientfd, (sockaddr*)&server_addr,sizeof(server_addr))==-1) { |
-
发送数据
使用send函数
-
接收数据
使用recv函数
1 |
|
2.3 test
3. 添加路由请求
1 | void setResponse(char *buff) |
在我们使用send函数之前使用这个函数进行处理,在浏览器中进行访问得到hello,后面我会继续完善