3

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

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();
}
4

3 回答 3

4

您可以使用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);
于 2013-03-23T16:16:35.503 回答
1

您可以自己实现解决方案的所有方面,即序列化、压缩、发送、接收等。大部分内容可以通过阅读WCFSystem.Net命名空间来找到。但是,我可以在这里使用网络库 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();
        }
    }
}

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

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

于 2013-03-23T15:20:25.770 回答
0

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

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

Parallel.ForEach(
   TaskManager(), item=>
   sw.WriteLine(item)
);
于 2013-03-23T15:09:51.243 回答