一、理解网络编程和套接字编程
1.1 socket套接字
网络编程又称为套接字编程,为什么要用套接字?我们把插头插到插座上就能从电网获得电力供给,同样为了与远程计算机进行数据传输,需要连接到因特网,而编程中的“套接字”就是用来连接该网络的工具。它本身就带有“连接”的含义,如果将其引申,则还可以表示两台计算机之间的网络连接。
1.1.1 一个例子来表示TCP的网络连接
因为拨打和接听是有区别的,因此需要分开看表示
-
接听方的流程如下:
- 首先需要安装一台电话机
2. 准备好电话机后要考虑分配电话号码的问题,这样别人才能联系到自己
3. 用blind函数给套接字分配地址后,电话机就装好了。接下来需要连接电话线并等待来电
4. 连接好电话线后,如果有人拨打就会响铃,这时候需要拿起电话线才能对话 -
打电话的流程如下:
- 和上面一样,调用socket套接字
- 调用connect函数
1.1.2 程序实现
所有的内容是在Linux系统下实现,因此该程序只支持Linux
服务端代码如下:
客户端代码如下:
实现:
代码获取:程序下载
我是用visual studio开发,在Linux虚拟机下部署文件并且实行,定位到两个文件位置,执行两个文件,注意在文件后面需要加一个端口号(这边用到9091,可以自定义5000-6535都可)
1.2 文件操作
1.2.1 文件描述符
实际上,文件描述符是为了方便称呼操作系统创建的文件或套接字而赋予的数。
试想一下,“把那本18号书帮我打印一下” 比 “把那本叫《物联网感知、识别与控制技术》的书帮我打印一下”是不是更简介明了?
文件描述符有时也称为文件句柄,但“句柄”主要是Windows中的术语。因此,本书中如果涉及Windows平台将使用“句柄”,如果是Linux平台则用描述符
分配给标准输入输出及标准错误的文件描述符。
文件描述符 | 对象 |
---|---|
0 | 标准输入:Standard Input |
1 | 标准输出:Standard Output |
2 | 标准错误:Standard Error |
- 打开文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *path, int flag);
/*
成功时返回文件描述符,失败时返回-1
path : 文件名的字符串地址
flag : 文件打开模式信息
*/
文件打开模式如下表:
打开模式 | 含义 |
---|---|
O_CREAT | 必要时创建文件 |
O_TRUNC | 删除全部现有数据 |
O_APPEND | 维持现有数据,保存到其后面 |
O_RDONLY | 只读打开 |
O_WRONLY | 只写打开 |
O_RDWR | 读写打开 |
- 关闭文件
#include <unistd.h>
int close(int fd);
/*
成功时返回 0 ,失败时返回 -1
fd : 需要关闭的文件或套接字的文件描述符
*/
- 将数据写入文件
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t nbytes);
/*
成功时返回写入的字节数 ,失败时返回 -1
fd : 显示数据传输对象的文件描述符
buf : 保存要传输数据的缓冲值地址
nbytes : 要传输数据的字节数
*/
在此函数的定义中,size_t 是通过 typedef 声明的 unsigned int 类型。对 ssize_t 来说,ssize_t 前面多加的 s 代表 signed ,即 ssize_t 是通过 typedef 声明的 signed int 类型。
- 读取文件中的数据
与之前的write()
函数相对应,read()
用来输入(接收)数据。
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t nbytes);
/*
成功时返回接收的字节数(但遇到文件结尾则返回 0),失败时返回 -1
fd : 显示数据接收对象的文件描述符
buf : 要保存接收的数据的缓冲地址值。
nbytes : 要接收数据的最大字节数
*/