C#通过单个端口传输多种数据类型(接收)

时间:2016-08-11 11:20:10

标签: c# tcp server client

问题

有一天,我有一个惊人的"我的 C#应用程序的想法。我没有为每种数据类型使用一个端口(文本,图像,文件),而是希望对所有三种数据类型使用单一端口。我非常接近实施这个。

到目前为止,我有一个 TcpListener 正在侦听端口 23722 。当 TcpClient 连接时,我开始使用StreamWriter.Write(datareceived);将传入数据写入文件,并且数据以特定模式出现(每行代表图像,文本消息或文件):

  

dnett {这是示例短信。)
dneti {NLtqmuvtGBdDY546 ... NLtqmuvtGBdDY546}
dnetf {Example.exe,NLtqmuvtGBdDY546 ... NLtqmuvtGBdDY546}

正如您在上面看到的图像和文件在发送之前转换为Base64 。要将它们转换回来,我会使用byte[] tmp = Convert.FromBase64String(string),但问题是我无法逐行读取文件,而数据仍在传入(使用写入) StreamWriter的)。另一个问题是,我不知道哪些数据已被处理(例如:哪些文件已经写入文件系统)。

我需要的是:

  • 同时读/写文件的解决方案
  • 知道哪些数据已经处理

  • 另一种做法(不同方法)

感谢

顺便说一下,我只有15岁,而英语不是我的第一语言,所以我很抱歉可能存在愚蠢的问题以及上述问题的错误。

2 个答案:

答案 0 :(得分:0)

我也是初学者。但我认为您可以使用ArrayList来转换所有行,直到所有行都被引用和发送。因此,当你准备好了,文件全部被引用时,yoy可以保存它。如果您询问如何知道识别哪种文件被发送,请先发送文件,您可以发送一个字符或字符串,允许其他程序等待文件识别该文件将被恢复。对不起我的英语。我希望我能帮到你。

答案 1 :(得分:0)

通常,您首先会发送"消息的大小"然后是实际的"消息" (来自服务器)。您可以将其扩展为首先发送消息类型的大小,然后发送消息类型,然后发送实际消息的大小,然后发送该消息。

要回头看,你可以这样做

using System;
using System.IO;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
using Newtonsoft.Json;
using Unity3DRemoteRendererClient.Helpers;

namespace Unity3DRemoteRendererClient.Communications.TCPCommunication {
 public sealed partial class TCPClientManager {
  public sealed class Receiver {
   private NetworkStream _stream;
   private Thread _thread;

   //Subscribe to this event if you want an event ever time data arrives.
   public event EventHandler < UnityToClientMessage > DataReceivedEvent;
   private static ManualResetEvent ShutDownEvent = new ManualResetEvent(false);

   public void Start(NetworkStream stream) {
    _stream = stream;
    _thread = new Thread(Run);
    _thread.Start();
   }

   private void Run() {
    try {
     // ShutdownEvent is a ManualResetEvent signaled by
     // Client when its time to close the socket.
     while (!ShutDownEvent.WaitOne(0)) {
      try {
       if (!_stream.DataAvailable) continue;

       //Read the first 4 bytes which represent the size of the message, and convert from byte array to int32
       var sizeinfo = new byte[4];
       _stream.Read(sizeinfo, 0, 4);
       var messageSize = BitConverter.ToInt32(sizeinfo, 0);

       //create a new buffer for the data to be read
       var buffer = new byte[messageSize];

       var read = 0;
       //Continue reading from the stream until we have read all bytes @messageSize
       while (read != messageSize) {
        read += _stream.Read(buffer, read, buffer.Length - read);
       }

       //I use flatbuffers, so you should deserialize yourself.
       var message = new UnityToClientMessage().FlatDeserialize(buffer);

       //raise data received event
       OnDataReceived(message);

      } catch (IOException ex) {
       // Handle the exception...
       throw;
      }
     }
    } catch (Exception ex) {
     // Handle the exception...
     throw;
    } finally {
     _stream.Close();
    }
   }

   private void OnDataReceived(UnityToClientMessage e) {
    EventHandler < UnityToClientMessage > handler = DataReceivedEvent;
    if (handler != null) {
     handler(this, e);
    }
   }

   public void ShutDown() {
    ShutDownEvent.Set();
   }

  }
 }
}

只需将其修改为首先读取消息类型消息的大小,然后再读取实际消息。一旦获得描述消息类型的消息,就可以执行switch语句,并相应地处理它。