【问题标题】:How can I send or return List<T> with socket如何使用套接字发送或返回 List<T>
【发布时间】:2013-03-23 15:04:32
【问题描述】:

还有一个服务器和客户端套接字。我想学习一种方法,如何将List&lt;T&gt;IEnumerable&lt;T&gt; 对象发送到客户端到服务器或服务器到客户端。 我想将服务器端 TaskManager 线程列表发送到客户端。此代码逐行发送,我想发送 complate 列表。我该怎么做?

private static IEnumerable<string> TaskManager()
{
    List<string> lst = new List<string>();

    foreach (System.Diagnostics.Process p in
    Process.GetProcesses().OrderBy(o => o.ProcessName))
    {
        lst.Add(p.ProcessName + "_" + p.Id);
    }
    return lst.AsParallel();
}

....
....
....

while (true)
{
    Socket socket = Listener.AcceptSocket();
    try
    {
        //open stream
        Stream stream = new NetworkStream(socket);
        StreamReader sr = new StreamReader(stream);
        StreamWriter sw = new StreamWriter(stream);
        sw.AutoFlush = true;
        while (true)
        {
            Parallel.ForEach(
                TaskManager(), item=>
                    sw.WriteLine(item)
                );
        }

        stream.Close();
        stream.Dispose();

    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

    Console.WriteLine("Disconnected: {0}", socket.RemoteEndPoint);
    socket.Close();
    socket.Dispose();
}

【问题讨论】:

    标签: c# winforms sockets c#-4.0


    【解决方案1】:

    您可以使用BinaryFormatter 对列表进行序列化和反序列化。

    using System.Runtime.Serialization.Formatters.Binary;
    
    // Server side
    Stream stream = new NetworkStream(socket);
    var bin = new BinaryFormatter();
    bin.Serialize(stream, TaskManager());
    
    // Client side
    Stream stream = new NetworkStream(socket);
    var bin = new BinaryFormatter();
    var list = (List<string>)bin.Deserialize(stream);
    

    【讨论】:

      【解决方案2】:

      您可以自己实现解决方案的所有方面,即序列化、压缩、发送、接收等。大部分内容可以通过阅读WCFSystem.Net 命名空间来找到。但是,我可以在这里使用network library NetworkComms.Net 为您提供一个非常简洁的解决方案。

      对于客户:

      using System;
      using NetworkCommsDotNet;
      
      namespace Client
      {
          class Program
          {
              static void Main(string[] args)
              {
                  //Create a connection
                  Connection connection = TCPConnection.GetConnection(new ConnectionInfo("127.0.0.1", 10000));
      
                  //Make a request for the threadIds and get the answer in one statement. 
                  string[] taskManagerThreadIds = connection.SendReceiveObject<string[]>("ThreadIdRequest", "ThreadIds", 2000);
      
                  Console.WriteLine("Server provided an array containing {0} ids", taskManagerThreadIds.Length);
      
                  Console.WriteLine("Send completed. Press any key to exit client.");
                  Console.ReadKey(true);
                  NetworkComms.Shutdown();
              }
          }
      }
      

      对于服务器:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Diagnostics;
      
      using NetworkCommsDotNet;
      
      namespace Server
      {
          class Program
          {
              static void Main(string[] args)
              {
                  NetworkComms.AppendGlobalIncomingPacketHandler<object>("ThreadIdRequest", (packetHeader, connection, incomingPlayer) =>
                  {
                      //Reply with the requested threadIds
                      Console.WriteLine("Received thread ID request from {0}.", connection.ToString());
                      connection.SendObject("ThreadIds", TaskManager().ToArray());
                  });
      
                  //Start listening for incoming TCP Connections
                  TCPConnection.StartListening(true);
      
                  Console.WriteLine("Server ready. Press any key to shutdown server.");
                  Console.ReadKey(true);
                  NetworkComms.Shutdown();
              }
      
              private static IEnumerable<string> TaskManager()
              {
                  List<string> lst = new List<string>();
      
                  foreach (System.Diagnostics.Process p in
                  Process.GetProcesses().OrderBy(o => o.ProcessName))
                  {
                      lst.Add(p.ProcessName + "_" + p.Id);
                  }
                  return lst.AsParallel();
              }
          }
      }
      

      您显然需要从website 下载 NetworkComms.Net DLL,以便将其添加到“使用 NetworkCommsDotNet”参考中。另请参阅客户端示例中的服务器 IP 地址当前为“127.0.0.1”,如果您在同一台机器上同时运行服务器和客户端,这应该可以工作。

      免责声明:我是这个库的开发者之一。

      【讨论】:

      • 它工作得很好,谢谢。但我想用 System.Net.Sockets 做到这一点
      • @ASPMaker - 我很高兴解决方案有效。 NetworkComms.Net 是使用 System.Net.Sockets 编写的。另请注意,您现在可以为您认为有用的答案投票。
      【解决方案3】:

      如果您想要一个可靠且健壮的解决方案,请使用 WCF 而不是自己实现序列化。

      此外,从并行线程写入流将无法正常工作。来自不同线程的部分行会混合在一起成为一些无形的垃圾:

      Parallel.ForEach(
         TaskManager(), item=>
         sw.WriteLine(item)
      );
      

      【讨论】:

        猜你喜欢
        • 2012-08-28
        • 2011-01-08
        • 2011-03-06
        • 2011-01-26
        • 2013-06-04
        • 2020-03-19
        • 1970-01-01
        • 2016-09-23
        • 2016-03-03
        相关资源
        最近更新 更多