简体   繁体   中英

Sending multiple messages over TCP

I asked a similar question before, but I just can't seem to find a way to do it. I understand that there is an issue with sending data over TCP since some data might be lost and some data might come as a part of the last message. I'm trying to fix them as I'm sending a set of commands from a list.

Here is my Client's code for sending:

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

        }

Here is my Server code for receiving:

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

        }

I was instructed to do something with size prefix and serialization, but I ran into trouble, and can't seem to get it to work.

I don't know what exactly do you mean by size prefix and serialization, but it's a good idea to let server know how many bytes should be expect from a client or alternatively "mark" the end of a messages somehow (ie. a string followed by two CRLF or a pseudo tag/comment like <eom> or <!--end of message-->). For the first option normally you have to use binary data. The second one seems easier for your sample code.

I can give you a working solution using the network library networkcomms.net as you requested. The code examples below send single strings. You can easily modify it to use string[] , List<string> etc by altering the server section

NetworkComms.AppendGlobalIncomingPacketHandler<string>

to

NetworkComms.AppendGlobalIncomingPacketHandler<string[]>

or

NetworkComms.AppendGlobalIncomingPacketHandler<List<string>>

The client side remains unchanged regardless of what you are sending. The code for the server would be as follows:

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

And for the client:

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

You will obviously need to download the NetworkCommsDotNet DLL from the website so that you can add it in the 'using NetworkCommsDotNet' reference. Also see the server IP address in the client example is currently "127.0.0.1", this should work if you run both the server and client on the same machine. For more information also checkout the getting started or how to create a client server application articles.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM