我正在开发一个应用程序,在该应用程序中,我使用套接字在服务器应用程序和客户端应用程序(web和桌面)之间进行通信
我的服务器应用程序持续侦听客户端应用程序的请求,并随时接受请求
服务器代码:
TcpListener listener = new TcpListener(IPAddress.Parse(ipAddStr), portNum);
listener.Start();
while (listen)
{
TcpClient handler = listener.AcceptTcpClient();
// doing some stuff
// for every client handler i am creating a new thread and start listening for the next request
}
对于web客户端,我使用WebSocket,至于与WebSocket客户端建立连接,我们必须遵循一些握手过程。为此,我使用了以下代码(运行良好):
static private string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
private static string AcceptKey(ref string key)
{
string longKey = key + guid;
SHA1 sha1 = SHA1CryptoServiceProvider.Create();
byte[] hashBytes = sha1.ComputeHash(System.Text.Encoding.ASCII.GetBytes(longKey));
return Convert.ToBase64String(hashBytes);
}
生成和发送与websocket客户端握手的响应:
// generate accept key fromm client header request
var key = headerRequest.Replace("ey:", "`")
.Split('`')[1]
.Replace("r", "").Split('n')[0]
.Trim();
var responseKey = AcceptKey(ref key);
//create the response for the webclient
var newLine = "rn";
var response = "HTTP/1.1 101 Switching Protocols" + newLine
+ "Upgrade: websocket" + newLine
+ "Connection: Upgrade" + newLine
+ "Sec-WebSocket-Accept: " + responseKey + newLine + newLine;
//send respose to the webclient
Byte[] sendBytes = Encoding.ASCII.GetBytes(response);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
我还有用于桌面应用程序的TcpClient
套接字,所以问题是如何识别请求是来自WebSocket
还是来自TcpClient
?
最简单的方法是让websocket侦听器和普通TCP侦听器侦听不同的端口号。无论如何,您都应该这样做,因为websocket应用程序通常在标准http端口80
上运行(当您使用带TLS的websocket时,则在标准https端口443
上运行),而基于TCP的自定义协议应该在1024到49151之间的"已注册"范围内的一个端口上运行。建议您遵循这一点,因为一个安全性良好的客户端环境允许web访问,但不允许用户连接到80和443以外的其他端口,而这些端口上的任何非http流量都可能触发入侵检测系统。
当您出于某种原因仍然希望在同一端口上处理两个协议时,这将有点困难。Websocket是一个基于TCP的协议,起初它看起来像一个普通的HTTPGET请求,直到您收到标头Connection: Upgrade
和Upgrade: websocket
。
这意味着对任一协议的连接请求首先都需要由同一侦听器接受。只有在客户端发送了足够的数据,将其连接尝试识别为您的自定义协议或websocket(或意外连接到您的端口的完全不同的东西-当您面向互联网部署应用程序时,您会遇到很多这种情况),然后将与客户端的通信委托给适当的处理程序类。
TcpClient是一个套接字包装器。
WebSocket是一种可以在TcpClient上运行的协议。WebSocket协议定义了握手以及如何对数据进行帧化。
区分简单TCP连接和WebSocket连接的最佳方法是让它们在不同的端口中侦听,因为您将使用不同的协议。如果你把它们放在同一个港口,那就太糟糕了,它会变得一团糟。