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 .

Ehsan Akbar
  • 6,977
  • 19
  • 96
  • 180
  • for more information please take a look at this :http://stackoverflow.com/questions/24349052/read-variables-of-a-message-that-is-sent-by-a-server-using-socket – Ehsan Akbar Jul 05 '14 at 12:59

2 Answers2

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.

Lucas Trzesniewski
  • 50,214
  • 11
  • 107
  • 158
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;
}
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
EZI
  • 15,209
  • 2
  • 27
  • 33
  • thank you let me write your code in my project and i will tell you the result – Ehsan Akbar Jul 05 '14 at 13:21
  • But i got a problem the values don't convert to binary they are integer ,for example 000200010003.....why ? – Ehsan Akbar Jul 05 '14 at 15:23
  • Ok i creat this messages CreateMessage(1, 2, 1, 1, 2, 1, 1, 1, 0);but the the output is 000100020001000100020001000100010000 – Ehsan Akbar Jul 05 '14 at 15:26
  • 1
    @EA I think you are confused with [endianness](http://en.wikipedia.org/wiki/Endianness), You can use *IPAddress.HostToNetworkOrder* and *IPAddress.NetworkToHostOrder* if you want – EZI Jul 05 '14 at 15:55