通过TCP发送多条消息

时间:2013-02-03 13:39:01

标签: c# client-server tcpclient

之前我问了一个类似的问题,但我似乎无法找到办法。 我知道通过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();
            }

        }

我被指示做一些带有大小前缀和序列化的东西,但我遇到了麻烦,似乎无法让它工作。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我可以根据您的要求使用network library 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”,如果您在同一台计算机上同时运行服务器和客户端,这应该可以工作。有关详细信息,请查看getting startedhow to create a client server application条款。