本帖最后由 惹尘 于 2015-10-20 20:15 编辑
TCP/IP通信与多线程技术
TCP/IP协议本身是比较复杂的,如果对协议本身展开专门研究,恐怕费九牛二虎之力也很难有多大的成就,但是经过这么多年的发展各个主流编程语言都将该协议封装起来,留给我们一个简单的接口,让我们像操作本机的文件来进行远程操作。所以在TCP/IP学习的过程中,重要的不是协议本身,而是在协议之上如何建立高效安全的运行机制。为了建立这种运行机制,我们在网络通信中使用了进程管理与多线程技术。 进程跟线程听起来是很抽象的技术,但任何抽象的东西都是日常生活的升华,为了帮助我们更好地理解进程跟线程我们用一个日常生活中的例子来进行阐述。大家都有去银行办理业务的经验,当你进入银行会有大堂经理接待,大堂经理会根据你所办的业务把你带到柜台、理财窗口、公司信贷窗口。在程序的世界里,进程就是银行,也就是程序本身,程序可以处理你遇到的一切问题,但你却不能为每个问题都建立一个进程,就像你不能为每个人单独建立一个银行一样,道理很简单—成本太高,建银行消耗的是真金白银,而开启进程消耗的是计算机有限的计算资源,为了节省资源我们引入了线程。我们先来看一下套接字通信的基本流程: 如图所示完整的套接字通信是服务器端建立套接字,然后与主机的某一端口绑定,接着监听该端口是否有来自客户端的请求。客户端建立套接字,然后向服务器端发出Connect请求,服务器端的监听函数Listen()监听到请求后调用Accept()函数建立连接,建立连接后服务器端和客户端都可以调用自己的Send()、Receive()函数发送或接受数据,通信完毕后断开连接。但细心的你也许会问大多数情况下并不是只有一个客户端,一个服务器往往会对应好多个客户端,面对多个客户端以上的程序智能等待一个客户端通信完毕后再为下一个服务。这就像银行来了客户,直接由大堂经理处理客户的所有需求,直到满足该客户的所有需求后再接待下一个客户,也就是说整个银行只能接待一个客户,这是不科学的!
银行为提高效率同时接待多个客户,聘请了大堂经理、理财经理、公司客户经理和柜员这些角色,其中大堂经理是一个关键的角色,因为你进入银行后首先要由大堂经理接待你,根据你的需求将你转交给柜员、理财经理、公司客户经理,然后继续在大堂接待新来的客户
在socket 通信的服务端中也有这么一个角色,即我们的listen 监听线程,在Client/Server 模式下,服务器需要不断监听来自多个客户端的请求,这时如果采用单线程机制的话,这个线程由于要不断的监听来自多个客户端的请求,从而无暇处理其他任务。要让服务器同时为多个客户服务,我们引入了多线程技术,而监听线程我们称之为主线程,该线程监听来自客户端的请求,接到请求后根据请求的种类立即交给相应的线程处理,然后继续监听来自新客户端的请求。由于大堂经理专门负责接待新来客户,所以无论你什么时候进入银行总会有大堂经理对你笑脸相迎,我们的服务器端程序也一样,不论几个新客户端同时发出请求,总会有listen 线程根据先来后到的顺序安排相应的线程为你服务。
我们用一个聊天室程序来说明我们线程之间的关系,首先我们对服务器的流程进行建模:
我们前期采用C#语言来进行学习,因为它编程相对比较简单,后期有兴趣地可以把它转化成java等各种高级语言,高级语言把套接字封装起来,让我们通过一个简单的函数就可以完成很多基础性的工作,在这里我们不多赘述,主线程调用AcceptTcpClient()函数监听来自客户端的请求,每监听到一个请求就为该请求建立一个线程,在线程中调用Receive()函数处理该客户端的请求,也许在下面的编程中你会发现每个线程中都有一个条件为真的循环,这在arduino中是不可能的因为arduino只有一个loop()函数,进入该函数后就不停地在loop()函数的范围内循环,几个while同时工作简直是开玩笑!这就是操作系统耍的一个小把戏,具体的原理深入讲起来复杂的很,你只需知道操作系统把cpu的计算资源分成一个个时间片,根据各个进程的优先级分给每个进程和线程,这样你看起来就会有多个条件为真得while同时工作了。
接下来设计服务器端的类图:
今天就先写到这儿吧,接下来会在编码实现的过程中详细讲解类图中各个变量跟函数的意思,如果大家觉得我写的内容有那么一点点意义的话,我就坚持写下去,因为diy对软件硬件都应该做到深入浅出,深入就是能够从原理上分析软硬件的本质从而找出问题的所在,浅出就是能从这些缤繁复杂的知识中升华出来,之汲取你想要的,希望对大家有一点启发,也希望我们智能创客有一个好的未来。
|