目录
第一章 理解网络编程和套接字
1.1 网络编程和套接字概要
网络编程就是编写程序使两台连网的计算机相互交换数据。首先需要的是物理连接,目前大部分计算机都连接到庞大的互联网中;在此基础上,只需考虑如何编写数据传输软件,而操作系统为我们提供了名为"套接字"的部件,套接字是数据网络传输用的软件设备。网络编程又称为套接字编程。
服务器端是能够受理连接请求的程序,服务器端创建的套接字称为服务器端套接字或监听套接字;客户端是用于请求连接的,客户端创建的套接字称为客户端套接字。
1.2 基于Linux的文件操作
在Linux系统中,套接字socket也被认为是文件的一种,因此在网络传输过程中可以使用文件I/O的相关函数;而Windows系统于Linux不同,要区分socket和文件,因此两种系统中的编程方式也不相同。之后主要学习的是Linux的编程方式。
1.2.1 底层文件访问和文件描述符
底层指的是与标准无关的操作系统独立提供的。文件描述符是系统分配给文件或套接字的整数,这个整数将成为程序员与操作系统之间良好沟通的渠道,是为了方便称呼操作系统创建的文件或套接字而赋予的数。有一些文件描述符是固定的,比如C语言中学习的标准输入输出及标准错误,即描述符从3开始由小到大的顺序编号,因为0、1、2是分配给标准I/O的描述符。
文件描述符 | 对象 |
0 | 标准输入:Standard Input |
1 | 标准输出:Standard Output |
2 | 标准错误:Standard Error |
文件和套接字一般经过创建过程才会被分配文件描述符。
1.2.2 打开文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *path, int flag);//成功时返回文件描述符,失败时返回-1
- path:文件名的字符串地址
- flag:文件打开模式信息
文件打开模式flag可能的常量值和含义:
打开模式 | 含义 |
O_CREAT | 必要时创建文件 |
O_TRUNG | 删除全部现有数据 |
O_APPEND | 维持现有数据,保存到其后面 |
O_RDONLY | 只读打开 |
O_WRONLY | 只写打开 |
O_RDWD | 读写打开 |
1.2.3 关闭文件
#include <unistd.h>
int close(int fd);//成功时返回0,失败时返回-1
- fd:需关闭的文件或套接字的文件描述符
此函数不仅可以关闭文件,也可以关闭套接字。
1.2.4 将数据写入文件
#include <unistd.h>
ssize_t write(int fd,const void *buf,size_t nbytes);//成功时返回写入的字节数,失败时返回-1
- ssize_t:signed int size_t:unsigned int 使用typedef声明的两个数据类型
- fd:显示数据传输对象的文件描述符
- buf:保存要传输数据的缓存地址值
- nbytes:要传输数据的字节数
用于向文件输出(传输数据);通过套接字向其他计算机传递数据。
1.2.5 读取文件中的数据
#include <unistd.h>
ssize_t read(int fd, void *buf,size_t nbytes);
- fd:显示数据传输对象的文件描述符
- buf:保存要接收数据的缓存地址值
- nbytes:要接收数据的最大字节数
第二章 套接字类型与协议设置
2.1 套接字协议及其数据传输特性
2.1.1 关于协议
协议是对话中使用的通信规则,在计算机领域内理解为计算机间对话必备通信规则。
2.1.2 创建套接字
#include <sys/socket.h>
int socket(int domain, int type, int protocol);//成功时返回文件描述符,失败时返回-1
- domain:套接字中使用的协议族信息
- type:套接字数据传输类型信息
- protocol:计算机间通信中使用的协议信息
头文件sys/socket.h中声明的协议族:
名称 | 协议族 |
PF_INET | IPv4互联网协议族 |
PF_INET6 | IPv6互联网协议族 |
PF_LOCAL | 本地通信的UNIX协议族 |
PF_PACKET | 底层套接字的协议族 |
PF_IPX | IPX Novell协议族 |
套接字类型Type指的是套接字的数据传输方式,因为决定了协议族并不能同时决定数据传输方式,一个协议族内存在多种数据传输方式:
- SOCK_STREAM:面向连接的套接字。
- 特征:
- 传输过程中数据不会消失
- 按序传输数据
- 传输的数据不存在数据边界
- 传输的数据不存在数据边界,指的是收发数据的套接字内部有缓冲(字节数组),因此收到数据并不意味着马上调用read函数,只要不超过缓冲容量,则有可能在数据填充满缓冲后1次read函数调用读取全部,也有可能分成多次read函数调用进行读取。在面向连接的套接字中,read函数和write函数的调用次数并无太大意义
- 面向连接的套接字连接必须一一对应,只能与另外一个同样特性的套接字连接
- 可靠的、按序传递的、基于字节的面向连接的数据传输方式的套接字
- 特征:
- SOCK_DGRAM:面向消息的套接字。
- 特征:
- 强调快速传输而非传输顺序
- 传输的数据可能丢失也可能损毁
- 传输的数据有数据边界
- 限制每次传输的数据大小
- 接收数据的次数应和传输次数相同
- 不可靠的、不按序传递的、以数据的高速传输为目的的套接字
- 特征:
第三个参数决定最终采用的协议。除非遇到同一协议族中存在多个数据传输方式相同的协议,大部分情况下可以向第三个参数传递0。
常用调用方式:
int tcp_socket = socket(PF_INET, SOCK_STREAM, 0);
0指的是满足PF