第十章
TCP协议,即传输控制协议(Transport Control Protocol),是一种面向连接的、可靠的传输层协议。TCP协议是为了在主机实现高可性包交换的传输协议,在计算机网络中用途很广泛。本章将通过C程序语言编程来实现一个基于TCP协议的程序,旨在向读者介绍TCP的实现原理,并进一步向读者介绍C语言网络编程技术。关于TCP的原理知识,读者可参见第2章。
10.1 设计目的
本章通过C 语言编程实现了一个TCP程序——包括服务器端程序和客户端程序,程序能实现基本的通信。通过本程序向读者展示了TCP的服务器端和客户端的操作流程,用以加深读者对TCP原理的理解。本章的部分知识点在前面章节也有所涉及,读者可以由此加深印象。
通过本章的学习,读者应该对以下知识点有一定的了解:Winsock版本的设置、Winsock库的加载以及Winsock错误号的获取;套接字的创建和关闭;TCP服务器的操作流程、客户端的操作流程;套接字的绑定、侦听、连接和接收操作;数据报的发送和接收;根据地址获取主机、根据主机名获取IP地址等信息;线程饿创建和参书设置;字符串比较函数的使用等。
读者可以在本章的基础上加以拓展,深刻理解TCP原理,掌握TCP编程方法和技巧,开发出自己的TCP程序。
10.2 功能描述
本章用C语言实现了基于TCP的服务器端和客户端程序,能实现基本的TCP通信。
其主要的功能包括如下。
(1) 服务器端能以默认选项(服务器端IP地址或主机名、端口号)启动,提供服务
功能。
(2) 服务器端能根据用户指定的选项(服务器端IP地址或主机名、端口号)启动,
提供服务和功能。
(3) 服务器以错误选项启动时,会提示错误信息,并终止程序。
(4) 客户端能连接到服务器端,发送消息到服务器端,同时也能接收来自服务器的
响应。
(5) 客户端不能连接到服务器端时,能输出错误信息。
(6) 客户端以错误选项启动时,会提示错误信息,并终止程序。
10.3总体设计
10.3.1 功能模块设计
1. 个功能模块图
本程序由两大部分组成,包括服务器端和客户端,如图10.1所示。服务器端包含的模块有初始模块、循环控制模块和服务模块;客户端包含的模块有初始化模块、功能控制模块和数据传输控制模块。
1) 服务器端
(1) 初始化模块用于初始化各个全局变量赋初始值。初始化Winsock,加
载Winsock库。
(2) 功能模块控制。该模块为其他模块提供调用的函数,包括参数获取功
能、用户帮助功能和错误输出功能 。
(3) 循环控制模块。该模块用于控制服务器端的服务次数,如果服务次数
超过指定的值则停止服务器。
(4) 服务模块。该模块为客户端提供服务功能,包括接收来自客户端的数
据,并发送数据到客户端。
2) 客户端
(1) 初始化模块。该模块用于初始化客户端的Winsock,加载Winsock库。 (2) 功能模块控制。与服务器端一样,该模块提供了参数获取、用户帮助
和错误输出功能。
(3) 数据传输控制模块。该模块控制着整个客户端的数据传输,包括数据
发送和接收等。
TCP程序设计 服务器端 客户端 初始化模块 功能控制模块 循环控制模块 服务模块 初始化模块 功能控制模块 数据传输控制模块 图 10.1 功能模块图 2. 服务器端系统流程图
服务器端系统流程图10.2所示。程序首先调用GetArgments()函数获取用户提供的先项,如果没有提供选项,则直接使用默认值,如果有选项提供并成功获取(选项错误则显示用户帮助并终止程序),则初始化变量和Winsock,并创建TCP流套接字;然后解析主机名(如果选项提供的是IP地址 ,或者使用是默认值)或者IP地址(如果选项提供的是主机名),解析成功后则设置服务器地址的各个参数,包括地址、IP
地址和端口号;接下来将创建的TCP流套接字和设定的服务器地址绑定(调用bing()函数);绑定成功后,则开始侦听客户的连接,调用循环控制函数LoopControl()函数和Service()函数作接收客户端的连接,接收数据、发送数据等操作;当服务数达到最多的服务次数时,并提示错误信息(调用ErrorPrint()函数实现)。
否
开始 获取参数 否 获取成功 是 初始化变量和Winsock 创建套接字 否 创建成功 是 解析主机名或者IP地址 否 解析成功 是 设置服务器地址参数 绑定地址与接字 否 绑定成功 是 侦听连接 侦听成功 是` 循环控制
输出相应
错误信息
图10.2 服务器端系统流程图 3. 客户端系统流程图
客户端系统流程图如图10.3所示。客户端程序执行时必须带选项,程序首先判断用户提供的参数个数,如果参数不等于3个,则比表明用户没有提供正确的选项,退出程序;如果参数等于3个,则调用GetArgments()函数获取用户提高的选项,如果获取的选项错误则显示用户帮助并终止程序,如果选项正确则开始创建TCP流套接字,成功创建TCP流套接字后则作和服务器类似的操作,即解析主机名或IP地址、设置服务器端地址;然后进行连接服务器操作,若能成功连接则输出连接信息,并发送消息到服务器端;然后接收来自服务器端的响应,(消息),并将接收到的消息输出。最后关闭套接字和释放占用的资源。和服务器一样,在操作过程中,任何一步操作失败都将退出程序,并提示错误信息(调用ErrorPrint()函数实现)。 显示用 户帮 助 开 始 否 释放资源关闭服务 结束 3个参是 获 取 参 数 否 获取成功 是 创 建 套 接 字 否 创建成功 解析主机名或者IP地址 否 解析成功 设置服务器地址参数 是 是
连 接服务否 连接成是 输出连接信息 发送 信息 到服 务 器 端 接收服务器端的响应 输出相应错误信息 释 放 资 源 关闭 套 接 字 结束 图 10.3 客户端系统流程图
4. 循环控制模块(服务器端)
该模块是服务器端用于循环控制的模块,其操作流程如图10.4所示。当服务器端侦听到客户连接时,调用该模块进行操作。首先接收客户端的请求,接收成功后,根据传入的参数is Multitasking判断是否要创建一个线程来服务客户端,如果 is Multitasking是1则创建线程来服务客户端(创建新线程时,设置了的初始堆栈大小为1000,线程执行函数是Service(),传递给Service()的参数为接收套接字),如果is Multitasking是0则直接调用 Service()函数来服务客户端。一次服务成功后,判断循环次数是否小于最大服务次数(可使用默认值,也可使用参数形式提供),如果已达到最大服务次数则关闭服务器,否则继续进行下一次服务。
开 始 接收客户端请求 否 接收成功? 是 否 创建线程?