0

I am trying to send data to a server from my client .the client sends messages to a server ,every message is 36 bytes and in this message every 4 byte is a field and in server part i should be able to detect that field from the message that client sends .Suppose i have this data :

A=21
B=32
c=43
D=55
E=75
F=73
G=12
H=14
M=12

In the client i should send this values as a single message .as you can see my message has 9 field and every field is 4 byte integer and all message is 36 byte.

So in server part when the message is received i should be able to separate the message and find the value of the fields .

In client application i am using this structure to send message to my server :

 m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            // Cet the remote IP address
            IPAddress ip = IPAddress.Parse(GetIP());
            int iPortNo = System.Convert.ToInt16("12345");
            // Create the end point 
            IPEndPoint ipEnd = new IPEndPoint(ip, iPortNo);
            // Connect to the remote host
            m_clientSocket.Connect(ipEnd);
    if (m_clientSocket.Connected)
                {

                    Object objData = ?!!!!;//My message
                    byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString());
                    if (m_clientSocket != null)
                    {
                        m_clientSocket.Send(byData);
                    }
                    Thread.Sleep(4000);

            }
}

And in server part i am using this code to receive the data:

public void OnDataReceived(IAsyncResult asyn)
        {
            try
            {
                SocketPacket socketData = (SocketPacket)asyn.AsyncState;

                int iRx = 0;
                // Complete the BeginReceive() asynchronous call by EndReceive() method
                // which will return the number of characters written to the stream 
                // by the client
                iRx = socketData.m_currentSocket.EndReceive(asyn);
                char[] chars = new char[iRx + 1];
                System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
                int charLen = d.GetChars(socketData.dataBuffer,
                                         0, iRx, chars, 0);
                System.String szData = new System.String(chars);
                MessageBox.Show(szData);

                // Continue the waiting for data on the Socket
                WaitForData(socketData.m_currentSocket);
            }
            catch (ObjectDisposedException)
            {
                System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
            }
            catch (SocketException se)
            {
            }
        }

Here is the other part of my server code :

 public void OnClientConnect(IAsyncResult asyn)
        {
            try
            {
                // Here we complete/end the BeginAccept() asynchronous call
                // by calling EndAccept() - which returns the reference to
                // a new Socket object
                m_workerSocket[m_clientCount] = m_mainSocket.EndAccept(asyn);
                // Let the worker Socket do the further processing for the 
                // just connected client
                WaitForData(m_workerSocket[m_clientCount]);
                // Now increment the client count
                ++m_clientCount;
                // Display this client connection as a status message on the GUI    
                String str = String.Format("Client # {0} connected", m_clientCount);


                // Since the main Socket is now free, it can go back and wait for
                // other clients who are attempting to connect
                m_mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
            }
            catch (ObjectDisposedException)
            {
                System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n");
            }


        }
        public class SocketPacket
        {
            public System.Net.Sockets.Socket m_currentSocket;
            public byte[] dataBuffer = new byte[36];
        }

In my form_load of server part i have this code:

    ipaddress = GetIP();
    // Check the port value

    string portStr = "12345";
    int port = System.Convert.ToInt32(portStr);
    // Create the listening socket...
    m_mainSocket = new Socket(AddressFamily.InterNetwork,
                              SocketType.Stream,
                              ProtocolType.Tcp);
    IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, port);
    // Bind to local IP Address...
    m_mainSocket.Bind(ipLocal);
    // Start listening...
    m_mainSocket.Listen(4);
    // Create the call back for any client connections...
    m_mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);

in fact i am trying to implement this link :

http://www.codeguru.com/csharp/csharp/cs_misc/sampleprograms/article.php/c7695/Asynchronous-Socket-Programming-in-C-Part-I.htm

My problem is how can i send my message as a 36 bytes via client and get and separate that from server ?

Every four bytes is a field and i should be able to get this value .

1

2 Answers 2

3

You're doing it wrong. If you want to transmit binary data, do not encode it as a string. There are multiple ways to do this:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Msg
{
    public int A, B, C, D, E, F, G, H, M;
}

Then use the Marshal class to get the bytes. This will get you little-endian on the wire data though.

Another method is to use a BinaryWriter. Same thing, little-endian data unless you convert it yourself or use an alternate version of BinaryWriter.

Then, it's much easier to use a NetworkStream, because this class will handle packet fragmentation for you. Here's the sending code using the BinaryWriter method:

using (var stream = new NetworkStream(stocket))
{
    var writer = new BinaryWriter(stream);
    writer.Write(21);
    writer.Write(32);
    // etc
}

Same thing on the client side using a NetworkStream and a BinaryReader.

NB: You can use async I/O with NetworkStream using the async/await feature.

Sign up to request clarification or add additional context in comments.

1 Comment

So i think the second method is better ,but i don't know how can combine it my application ?
1

Seems like all you need is 2 methods to convert integers to byte-array and vice versa:

byte[] packet =  CreateMessage(21,32,43,55,75,73,12,14,12);
//send message
//recv message and get ints back
int[] ints =  GetParameters(packet);

....

public byte[] CreateMessage(params int[] parameters)
{
    var buf = new byte[parameters.Length * sizeof(int)];
    for (int i = 0; i < parameters.Length; i++) 
        Array.Copy(BitConverter.GetBytes(parameters[i]), 0, buf, i * sizeof(int), sizeof(int));
    return buf;
}

public int[] GetParameters(byte[] buf)
{
    var ints = new int[buf.Length / sizeof(int)];
    for (int i = 0; i < ints.Length; i++)
        ints[i] = BitConverter.ToInt32(buf, i * sizeof(int));
    return ints;
}

4 Comments

thank you let me write your code in my project and i will tell you the result
But i got a problem the values don't convert to binary they are integer ,for example 000200010003.....why ?
Ok i creat this messages CreateMessage(1, 2, 1, 1, 2, 1, 1, 1, 0);but the the output is 000100020001000100020001000100010000
@EA I think you are confused with endianness, You can use IPAddress.HostToNetworkOrder and IPAddress.NetworkToHostOrder if you want

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.