【问题标题】:C# Transferring multiple data types over a single port (receiving)C# 通过单个端口传输多种数据类型(接收)
【发布时间】:2016-08-11 11:20:10
【问题描述】:

问题

前几天,我对我的 C# 应用程序 有了一个“惊人”的想法。我不想为每种数据类型(文本、图像、文件)使用一个端口,我想为所有三种数据类型使用一个一个端口。我非常接近实现这一点。

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

dnett{这是一个示例文本消息。)
dneti{NLtqmuvtGBdDY546 ... NLtqmuvtGBdDY546}
dnetf{Example.exe,NLtqmuvtGBdDY546 ... NLtqmuvtGBdDY546}

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


我需要的是:

  • 一种同时读/写文件的解决方案
  • 了解哪些数据已被处理

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

谢谢

顺便说一句,我只有 15 岁,英语不是我的第一语言,所以对于可能愚蠢的问题和上述问题中的错误,我深表歉意。

【问题讨论】:

标签: c# tcp server client


【解决方案1】:

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

要回读,你会做这样的事情

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 语句,并相应地处理它。

【讨论】:

  • 注意:你必须稍微玩一下才能让它适合你的目的 - 我现在在火车上和我的手机上,所以我不能很容易地修改。跨度>
  • 另外,最好发送原始数据而不是将其更改为 base64 并再次返回。我使用 flatbuffers,这太棒了。
  • 谢谢,这真的很有帮助。
  • 没问题。如果您需要更多帮助,我可以稍后在我使用笔记本电脑时提供帮助。
  • 实现了,先打包发送类型和大小,其他都是数据,直到达到大小。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2011-09-13
    • 1970-01-01
    • 2014-10-11
    • 2020-08-10
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多