使用套接字与客户端和服务器通信

时间:2016-08-25 06:47:01

标签: c# sockets tcp networkstream

所以我编写了代码,以便与服务器和客户端进行通信。

  • 第一个问题是服务器如何识别它与实际客户端的通信,而不是使用该端口的其他人,我听说浏览器使用SHA散列验证服务器。
  • 第二个问题是关于在变量中发送和接收数据的最佳方式,以及识别哪个是哪个,因为当前分割数据的方法看起来不太优雅。

接收和发送数据的服务器端代码:

NetworkStream NetStream1 = TCPSocket.GetStream();                       
NetStream.Read(Buffer, 0, Buffer.Length);
ReceivedData = System.Text.Encoding.ASCII.GetString(Buffer);
string[] splitter = ReceivedData.Split('-');
Variable1 = splitter[0];
Variable2 = splitter[1];
//send response
SendBuffer = Encoding.ASCII.GetBytes(ResultINT1+"-"+ResultINT2);
NetStream.Write(SendBuffer, 0, SendBuffer.Length);
NetStream.Flush();

发送和接收的客户端代码

NetworkStream SendStream = ClientSocket.GetStream();
byte[] SendBuffer = System.Text.Encoding.ASCII.GetBytes(V1+"-"+V2);
SendStream.Write(SendBuffer, 0, SendBuffer.Length);
SendStream.Flush();
//response
SendStream.Read(RecieveBuffer, 0, RecieveBuffer.Length);
string ResultString = System.Text.Encoding.ASCII.GetString(RecieveBuffer);
string[] splitted = ResultString.Split('-');
int R1 = Convert.ToInt32(splitted[0]);
int R2 = Convert.ToInt16(splitted[1]);

4 个答案:

答案 0 :(得分:2)

  1. 提供一些身份验证机制
  2. 使用一些序列化程序。

答案 1 :(得分:1)

您的第一个问题涉及身份验证,这是一个很大的主题,并且有许多可能的实现,尽管我不确定您对“正在使用该端口的其他人”的确切含义。您的服务器应始终位于同一端口 - 即客户端识别服务的方式。

关于你的第二个问题,还有很多可能性,但我建议初学者最简单的方法是使用 XmlSerializer 和一个简单的信息信封。

  1. 使用简单的公共属性创建XmlSerializable类,或者使用XmlElementAttribute,XmlRootAttribute等进行装饰。
  2. 序列化为MemoryStream
  3. 写入信封中包含的内存流中的字节(请参阅下文)
  4. 完整信封接收到字节数组中。
  5. 从字节数组
  6. 构造一个MemoryStream
  7. 使用XmlSerializer重建原始对象的副本。
  8. 信封很关键。最简单的只是序列化对象的二进制长度。大多数协议通常会使用CRC来扩展它以处理可能的损坏,但由于以太网使用强CRC并且TCP是可靠的传输(尽管CRC很弱),这通常是过度的。初学者错过的关键点是TCP是一种流媒体协议而不是基于消息的协议,因此发送者完全可以进行1000字节的单次写入,而接收者则将其作为一些较小的块接收。这就是为什么你需要某种方法来检测消息的结束,例如使用长度以及为什么接收器需要累积接收的块,直到收到完整的消息(可能是下一个消息的一部分)并且可以反序列化。

    这可能看起来很复杂但不幸的是,在TCP级别,它没有比这更简单:(

答案 2 :(得分:0)

  

第一个问题是服务器如何识别它与实际客户端的通信,而不是使用该端口的其他人,我听说浏览器使用SHA散列验证服务器。

服务器可以通过其IP地址识别不同的客户端。见StreamReader.ReadToEnd

  

第二个问题是关于在变量中发送和接收数据的最佳方式,以及确定哪个是哪个,因为当前分割数据的方法看起来并不优雅。

这取决于您的协议架构,但是在网络上交换值的可移植方式是将它们保持为文本格式(这样就不存在字节序,类型大小......)。

说,请注意您的变量分隔符:'-'可能难以使用负数,' '';'更常见。

答案 3 :(得分:0)

您可能想要定义某种类型的通信协议 - 基于文本的协议开始时最直接 - 您可以读取和写入"命令"每个都在一个单独的行上。

首先,会有一个"握手",客户端会发送类似" HELLO my-awesome-protocol-v1 \ n"并且服务器会以类似的方式响应通过这种方式,您可以确保其他人是了解协议的客户端,或者您可以关闭不实现协议的连接。

然后可能有某种方式使用" VAR variableName 123.45 \ n"等命令发送变量值。您可以阅读https://en.wikipedia.org/wiki/Text-based_protocol并查看http://www.ncftp.com/libncftp/doc/ftp_overview.html获取灵感。