陈艳军 温占考 周胜群
摘要:该文首先分析了TCP/IP协议的基本概念和Socket编程的基本原理,重点在于用C#实现了基于TCP/IP网络通信的长/短连接切换的程序模型,核心在于改进传统Socket连接中服务器的性能,根据需要进行长短连接的切换,有效的提高了连接效率及网络通信性能。该文对理解Socket通信原理和实际开发高效Socket应用程序有较大的参考价值。
关键词:TCP/IP;Socket长连接;Socket短连接
中图分类号:TP393 文献标识码:A 文章编号:1009-3044(2014)08-1692-03
1 TCP/IP与Socket关系
TCP/IP协议(Transmission Control Protocol/Internet Protocol)定义了网络设备如何接入Internet以及数据如何在它们之间传输的标准。协议采用了四层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。如今TCP/IP协议已经成为计算机网络协议事实上的标准。如图1表明了这些协议的关系。
在计算机网络体系的TCP/IP四层结构中,终端的应用进程要相互通信,网络层为两端提供了逻辑通信,运输层为两端应用进程提供了端到端的逻辑通信。而TCP/IP协议簇的一个接口,提供了可靠的运输层协议。这就表明应用程序在使用数据传输之前,必须建立TCP连接。在传输数据完毕后,必须释放已经建立的TCP连接。其中,每一条TCP连接只能是点对点的,TCP连接的端点不是主机,不是主机的IP地址,不是应用进程,也不是传输层的协议端口号,而是套接字(Socket)。绑定端口号及IP地址即构成套接字。图2说明了应用程序、套接字、协议之间的关系。
2 Socket的长/短连接
Socket通信在客户端与服务器端的连接上分为长连接和短连接。具体的说,长连接指在客户机和服务器连接后,可以连续发送数据包,当没有数据包发送时,该连接一直保持,但这种建立起来的连接是不稳定的。一般在較长时间没有数据传输的情况下,双方需要发送“心跳包”来维持该连接有状态。长连接一般的步骤是:连接→数据传输→保持连接(心跳)→数据传输→保持连接(心跳)→……→关闭连接;
短连接是指客户端和服务端在需要通信时就建立一个Socket连接,在数据传输完成后关闭此连接。比如银行一般都采用短连接。短连接一般的步骤是:连接→数据传输→关闭连接;
下面分析一下使用长连接和短连接的典型环境。当数据在两端传输比较频繁,而且连接数不太多的情况下一般使用长连接。因为每个TCP的连接都需要三次握手,如果使用短连接不断的建立连接在关闭。这样就耗费了大量的时间,而且降低了网络通信的效率。所以在建立连接后不断开,通信时直接发送数据包就行。例如:数据库的连接一般使用长连接,如果用短连接频繁的通信会造成Socket错误。又如HTTP服务,只是连接、请求、关闭。这个过程时间较短,服务器在响应后即可关闭连接。
其实长连接是相对于通常的短连接而说的,也就是长时间保持客户端与服务端的连接状态。
3 Socket网络通信长/短连接切换的C/S模型
Socket网络通信是C/S(Client/Server)模型在互联网上最常用的方式之一。服务器(Server)始终运行,所以用死循环来完成,其一直监听客户机(Client)的连接。当客户端发出连接时,服务器即可获得一个用于通信的套接字,客户机使用该套接字与服务器进行通信。本文采用长/短连接切换的C/S模型,其在服务器端设置了两层循环,第一层循环为死循环,重复监听客户端的Socket连接请求。第二层循环进行长/短连接的切换。本模型中添加了一个标志变量,在标志变量表示为长连接时,第二层循环始终保持,当标志变量为短连接时,退出第二层循环。图3说明了本模型中客户机与服务器进行长/短连接切换的通信步骤。
4 Socket通信中客户端的实现
客户端向服务器发起连接请求后,就被动的等待服务器的响应。下面给出主要的重点代码,典型的TCP客户端也都包括了以下内容:
1)创建一个Socket实例。用于向指定的远程主机和端口建立一个TCP连接。
Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个Socket
IPEndPoint iep =new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);
2)通过发送ShortComT/ ShortComF字符串来确定当下是采用长连接还是短连接。字符串”ShortComT”为短连接,字符串”ShortComF”为长连接。
//跟服务器Socket连接,建立长连接
public static Socket CreatLongLink(){
c.Connect(ipe);//连接到服务器
byte[] sendbytes = Encoding.Default.GetBytes("ShortComF");
c.Send(sendbytes, sendbytes.Length, 0);
return c;
}//关闭长连接,服务器切换至短连接
public static void CloseLongLink(Socket c){
//发送一个短连接命令
Byte[] sendbytes = Encoding.Default.GetBytes("ShortComT");
c.Send(sendbytes, sendbytes.Length, 0);
c.Close();}
5 Socket服务器端的性能改进
服务器端的设计采用长/短连接可切换的方式,这样可以根据系统的实际需求,来采用具体的连接方式,在实际项目中,有时候数据的传输比较少,有时候传输又比较频繁。为了提高服务器的性能,节约网络资源,设计了一种长/短连接可切换的模型。要注意异常处理代码的编写。
private Thread _listenerThread = null; //定义线程,用于开启服务器Socket监听
private Socket _serverSocket = null; //定义服务器Socket对象
private bool shortCom = true; //定义长/短连接标志,Socket通信默认为短连接
//包含应用程序连接到主机上的服务所需的主机和本地或远程端口信息。通过组合服务的主机 IP 地址和端口号
IPEndPoint iep =new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);
//线程运行定义的方法,主要是开启服务器Socket监听
_listenerThread = new Thread(new ThreadStart(SocketServerRun));
_listenerThread.Start();
//定义方法,开启服务器Socket监听,通过对客户端发送的连接标志进行判断来切换长/短连接
private void SocketServerRun(){
//创建基于TCP协议的服务器端Socket对象
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(iep);//绑定端口及IP
_serverSocket.Listen(0);//开始监听
try{do{//本层循环为了不断地监听客户端的Socket连接请求
Socket _clientSocket= _serverSocket.Accept();//阻塞直到有客户端Sokcet请求
do{//本层循环用于长连接,由长/短连接标志变量控制
byte[] recvCMDBytes = new byte[1024];
string recvCMDStr += Encoding.Default.GetString(recvCMDBytes, 0, _clientSocket.Receive(recvCMDBytes, recvCMDBytes.Length, 0)); //从客户端接受信息
if (recvCMDStr.Length > 0){
switch (recvCMDStr){
case "ShortComT": //短连接命令
shortCom = true;
break;
case "ShortComF"://长连接
shortCom = false;
break;
case ……: //其他
…… //处理事务
break;
}}} while (!shortCom);
//断开客户端的连接
_clientSocket.Close();
} while (true);
}catch (Exception ex){ //异常出现,重启服务器的Socket监听
shortCom = true; //默认线程短连接
_serverSocket.Close();//Socket关闭
_listenerThread = new Thread(new ThreadStart(SocketServerRun));// 重启服务器的Socket监听
_listenerThread.Start();
}}
6 总结
本文介绍了TCP/IP网络编程的原理及Socket的相关知识,提出了服务器端的Socket连接方式的优化方案,读者可以针对实际项目的需求,合理地选择Socket服务器端的连接类型,同时本文还提供了较实用的参考代码。使用长/短连接切换技术实现了特定场合C/S架构下Socket编程的需求。对相关开发人员有一定的启发意义。
参考文献:
[1] 谢希仁.计算机网络[M].北京:电子工业出版社,2013(6).
[2] 陈浩,张伟.基于java socket的TCP/IP网络编程 [J].计算机光盘软件与应用,2013(1).
[3] http://blog.csdn.net/shanliangliuxing/article/details/7743917.
[4] 罗亚非.基于TCP的Socket多线程通信[J].电脑知识与技术,2009(2).
[5] 刘骏,颜钢锋.基于Socket的网络编程技术及其实现[J].江南大學学报,2004(3).