目录
1.4 基于Windows平台的网络初始化和注销(Linux平台无需该操作)
一、网络编程基础
1.1 套接字
网络编程又称套接字(socket)编程。“套接字”是网络数据传输用的软件设备,可以引申为两台计算机之间的网络连接。
1.2 服务器端套接字
服务器端(server)是用于受理套接字连接请求的程序,其创建的套接字称为监听套接字。创建步骤为:
1)调用socket函数创建套接字;
2)调用bind函数分配IP地址和端口号;
3)调用listen函数将套接字转为可接受状态;
4)调用accept函数受理连接请求。如果没有连接请求下调用该函数,则不会返回,直到有连接请求为止;
5)收发数据;
1.3 客户端套接字
客户端(client)是用于请求连接的程序。创建步骤为:
1)调用socket函数创建套接字;
2)调用connect函数相服务器端发送请求连接;
3)收发数据;
额外知识:
像size_t、socklen_t等数据类型,都属于元数据类型(primitive)。在头文件中一般由typedef声明。原因是在程序移植中,不同电脑的long int等数据类型所占的字节数可能不同。如果使用size_t、socklen_t,只需修改size_t、socklen_t的typedef声明即可。在项目中,为了给基本类型赋予别名,都会添加大量typedef声明,而为了与程序员定义的新类型区分,操作系统定义的数据类型会添加后缀_t。
1.4 基于Windows平台的网络初始化和注销(Linux平台无需该操作)
Windows套接字大部分参考BSD系列UNIX套接字设计的。
1.4.1设置头文件和库
Windows上开发网络程序,需要以下两步:
导入头文件winsock2.h
链接ws2_32.lib库
链接ws2_32.lib库的步骤:打开项目的“属性”页;选择“配置属性”——“链接器”——“输入”——“附加依赖项”;在“附加依赖项”中填入ws2_32.lib。
1.4.2winsock初始化
进行winsock编程前,必须调用WSAStartup函数。该函数有两个参数,第一个为版本号,第二个为结构体地址。
若版本号为1.2,其中1是主版本号,2是副版本号,应传递ox0201。但以字节为单位构造版本信息有些麻烦,可以使用MAKEWORD宏函数构造版本信息:MAKEWORD(1,2); //版本号为1.2,返回ox0201
第二个参数需传入WSADATA型结构体变量地址(LPWSADATA是WSADATA的指针类型)。
1.4.3winsock注销
调用该函数,winsock将无法调用winsock相关函数。
1.5 I/O函数
send函数和recv函数来自于BSD套接字,不只是Windows独有,Linux也有同样的函数。
二、套接字类型与协议设置
2.1 套接字函数socket(以Linux系统为例)
int socket(int domain, int type, int protocol);
参数domain:套接字使用的协议簇(Protocol Family)信息;
参数type:套接字数据传输类型信息;
参数protocol:计算机通信中使用的协议信息;
函数成功返回一个文件描述符;失败返回-1。
2.2 协议簇
名称 | 协议簇 |
---|---|
PF_INET | IPv4互联网协议簇 |
PF_INET6 | IPv6互联网协议簇 |
PF_LOCAL | 本地通信的UNIX协议簇 |
PF_PACKET | 底层套接字协议簇 |
PF_IPX | IPX Novell协议簇 |
2.3 数据传输类型
决定了协议簇并不能同时决定数据传输方式。
名称 | 面向连接的套接字 (SOCK_STREAM) |
面向消息的套接字 (SOCK_DGRAM) |
---|---|---|
特点 | 1.传输过程数据不会消失 2.按序传输数据 3.不存在数据边界 4.连接必须一一对应 5.可靠 |
1.强调快速传输而非传输顺序 2.数据可能丢失 3.数据存在边界 4.限制每次传输数据大小 5.不可靠 |
结果 | 1.如果传输出错还会提供重传服务 2.套接字缓冲已满会停止套接字传输,但不会丢失数据 3.多个write函数才调用一个read函数 |
2.4 协议类型
一般第三个参数为0,因为由前两个参数即可创建套接字。但在少数情况下,同一协议簇可能存在多个数据传输方式相同的协议,这是就需要传递第三个参数。
三、地址簇与数据序列
3.1 端口号复用问题
端口号由16位构成,可分配的端口号范围是0~65535.但0~1023是知名端口号,一般分配给特定应用程序。另外,TCP和UDP不会公用端口号,所以允许重复。例如:某个TCP使用9190号端口,那么其他TCP不能使用该端口号,但UDP可以使用9190号端口。解释如下图: