0

我之前问过类似的问题,但我似乎无法找到解决方法。我了解通过 TCP 发送数据存在问题,因为某些数据可能会丢失,并且某些数据可能会作为最后一条消息的一部分出现。我正在尝试修复它们,因为我正在从列表中发送一组命令。

这是我的客户发送代码:

private void sendBtn_Click(object sender, EventArgs e)
        {
            try
            {
                for (int i = 0; i < listORequestedCommands.Items.Count; i++)
                {
                    clientSock.Send(Encoding.Default.GetBytes(listORequestedCommands.Items[i].ToString()), listORequestedCommands.Items[i].ToString().Length, SocketFlags.None);
                }
                removeAll_Click(sender, e);
                sendBtn.Enabled = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error!");
                this.Close();
            }

        }

这是我的接收服务器代码:

private void clientReceived(Client sender, byte[] data)
        {
            try
            {
                Invoke((MethodInvoker)delegate
                {
                    for (int i = 0; i < lstClients.Items.Count; i++)
                    {
                        Client client = lstClients.Items[i].Tag as Client;

                        if (client.ID == sender.ID)
                        {
                            string incommingCommand = Encoding.Default.GetString(data);
                            if (incommingCommand.CompareTo("") != 0)
                            {
                                lstClients.Items[i].SubItems[1].Text = incommingCommand;
                                string[] splittedIncommingCommand = incommingCommand.Split(' ');

                                int numRunProc = 0;

                                do
                                {
                                    numRunProc = countProcesses();
                                }
                                while ((numRunProc >= maxProcesses) || (numRunProc + Int32.Parse(splittedIncommingCommand[splittedIncommingCommand.Length - 1]) >= maxProcesses));

                                Process processToRun = new Process();
                                processToRun.StartInfo.FileName = splittedIncommingCommand[0];
                                processToRun.StartInfo.WorkingDirectory = Path.GetDirectoryName(splittedIncommingCommand[0]);
                                processToRun.StartInfo.Arguments = "";

                                for (int j = 1; j < splittedIncommingCommand.Length; j++)
                                {
                                    processToRun.StartInfo.Arguments += " " + splittedIncommingCommand[j];
                                }

                                processToRun.Start();
                            }
                            break;
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error!");
                this.Close();
            }

        }

我被指示使用大小前缀和序列化做一些事情,但我遇到了麻烦,似乎无法让它工作。

4

2 回答 2

0

我可以按照您的要求使用网络库networkcomms.net 为您提供一个可行的解决方案。下面的代码示例发送单个字符串。您可以通过更改服务器部分轻松修改它以使用string[]List<string>

NetworkComms.AppendGlobalIncomingPacketHandler<string>

NetworkComms.AppendGlobalIncomingPacketHandler<string[]>

或者

NetworkComms.AppendGlobalIncomingPacketHandler<List<string>>

无论您发送什么,客户端都保持不变。服务器的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NetworkCommsDotNet;

namespace TCPServer
{
    class Program
    {
        static void Main(string[] args)
        {
            NetworkComms.AppendGlobalIncomingPacketHandler<string>("Message", (packetHeader, connection, incomingString) => 
            {
                    Console.WriteLine("The server received a string - " + incomingString);
                    //Perform any other operations on the string you want to here.
            });

            TCPConnection.StartListening(true);

            Console.WriteLine("Server ready. Press any key to shutdown server.");
            Console.ReadKey(true);
            NetworkComms.Shutdown();
        }
    }
}

对于客户:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NetworkCommsDotNet;

namespace TCPClient
{
    class Program
    {
        static void Main(string[] args)
        {
            string messageToSend = "This is the message to send";
            TCPConnection.GetConnection(new ConnectionInfo("127.0.0.1", 10000)).SendObject("Message", messageToSend);

            Console.WriteLine("Press any key to exit client.");
            Console.ReadKey(true);
            NetworkComms.Shutdown();
        }
    }
}

您显然需要从网站下载 NetworkCommsDotNet DLL,以便将其添加到“使用 NetworkCommsDotNet”参考中。另请参阅客户端示例中的服务器 IP 地址当前为“127.0.0.1”,如果您在同一台机器上同时运行服务器和客户端,这应该可以工作。有关更多信息,还请查看入门如何创建客户端服务器应用程序文章。

于 2013-02-03T15:18:11.360 回答
0

我不知道大小前缀和序列化到底是什么意思,但最好让服务器知道客户端应该有多少字节,或者以某种方式“标记”消息的结尾(即字符串后跟两个 CRLF 或伪标记/注释,如 <eom> 或 <!--end of message-->)。对于第一个选项,通常您必须使用二进制数据。对于您的示例代码,第二个似乎更容易。

于 2013-02-03T14:29:04.720 回答