2013-02-03 136 views
0

我之前问过类似的问题,但我似乎无法找到一种方法来做到这一点。 我知道在通过TCP发送数据时存在问题,因为有些数据可能会丢失,有些数据可能会成为最后一条消息的一部分。 我试图解决它们,因为我从列表发送一组命令。通过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(); 
      } 

     } 

我奉命做一些与大小前缀和系列化,但我遇到了麻烦,似乎无法让它工作。

+0

您是否有兴趣了解底层结构或只是针对您的问题的工作解决方案? – MarcF

+0

您对TCP的理解不正确:TCP确保按顺序传递数据包,而不会丢失数据包。详情请参阅http://en.wikipedia.org/wiki/Transmission_Control_Protocol。 –

+0

实际上我对这两个都很感兴趣,现在我只需要一个解决方案,因为我需要发布一个版本。但是,我也想了解它以备将来使用。谢谢。 – Idanis

回答

0

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

+0

是的,这更像是我听说过的解决方案。请告诉我如何做到这一点,因为这是我在'clientSock.Send ...'系列发布的代码上尝试的。如果你也可以解释,那会很好。谢谢! – Idanis

+0

从你的列表创建一个字符串,添加一个结束标记(即listORequestedCommands.Items [i] .ToString()+“”)并从客户端发送它。调整您的服务器端代码以从客户端读取字符串,直到它结束与“”。就这样。 – 2013-02-03 14:53:15

0

我可以根据您的要求为您提供一个使用network library networkcomms.net的工作解决方案。下面的代码示例发送单个字符串。您可以轻松地修改它通过改变服务器部分

NetworkComms.AppendGlobalIncomingPacketHandler<string> 

使用string[]List<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文章。