Search Unity

C# TCP/IP Socket - How to receive from server?

Discussion in 'Scripting' started by chiapekharn, Feb 9, 2014.

  1. chiapekharn

    chiapekharn

    Joined:
    Aug 22, 2012
    Posts:
    11
    Hi ,

    I've managed to get connected with the server using a TCP socket, but I didn't get any responses. I was thinking I should do a TCP Listener instead but all the TCP listener I did wasn't working at all (it's because it's for server use only? http://msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx)

    Here's the code I've managed to get it connected, but I'm not sure if the socket is still open to receive incoming data, and if not, do I need to create a TCP listener? Here's the link where I refer it to: http://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx

    private void SetupSocket()
    {
    Debug.Log("Starting socket for server");

    string JHServerIP = PlayerPrefs.GetString("JHServerIP", "");
    port = int.Parse(PlayerPrefs.GetString("JHServerPort", ""));
    string gameToken = PlayerPrefs.GetString("JHGameToken", "");
    gameID = PlayerPrefs.GetString("JHGameID", "");

    Debug.Log("JH Server IP : " + JHServerIP);
    Debug.Log ("JH Port : " + port);
    Debug.Log ("JH Game Token : " + gameToken);
    Debug.Log ("JH Game ID : " + gameID);

    string strXML = "<qpxsd:qpreq msgid='00002' xmlns:qpxsd='urn:qpns'><connectionreq><account_id>" + playerAccountID + "</account_id><game_id>" + gameTypeID + gameID + "</game_id><token>" + gameToken + "</token></connectionreq></qpxsd:qpreq>";
    string myStrXML = WWW.UnEscapeURL(strXML);

    // Connect to a remote device.
    try {
    // Establish the remote endpoint for the socket.
    IPAddress ipAddress = IPAddress.Parse(JHServerIP);
    IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

    Debug.Log("ipAddress : " + ipAddress);
    Debug.Log ("remoteEP : " + remoteEP);

    // Create a TCP/IP socket.
    Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    // Connect to the remote endpoint.
    client.BeginConnect( ipAddress, port, new AsyncCallback(ConnectCallback), client);
    Debug.Log("1) Is connected? " + client.Connected);
    connectDone.WaitOne();
    Debug.Log("2) Is connected? " + client.Connected);

    // Send test data to the remote device.
    Debug.Log(myStrXML);
    Send(client, myStrXML);
    sendDone.WaitOne();
    Debug.Log("3) Is connected? " + client.Connected);

    // Receive the response from the remote device.
    Receive(client);
    receiveDone.WaitOne();
    Debug.Log("4) Is connected? " + client.Connected);

    // Write the response to the console.
    //Console.WriteLine("Response received : {0}", response);
    Debug.Log("Response received : " + response);
    Debug.Log("5) Is connected? " + client.Connected);

    if (client.Connected)
    {
    }

    // Release the socket.
    //client.Shutdown(SocketShutdown.Both);
    //client.Close();

    } catch (Exception e) {
    Debug.Log(e.ToString());
    }
    }
     
  2. Vulegend

    Vulegend

    Joined:
    Jul 15, 2012
    Posts:
    84
    I can see you're using sync sockets to send/'recieve data. In that case you would want to have a method that will check the RecievedBuffer property. If the property is lesser or equal to zero no data was received from the server , otherwise you can process data normaly.

    I wouldn't recommend TCPListener , it's a bad abstraction that combines few methods into one.

    Tho , i'd pretty much use async sockets , unless you have specific needs to use sync sockets. Here's an example of async receiving.

    Code (csharp):
    1.  
    2.  
    3. using UnityEngine;
    4. using System.Collections;
    5. using System;
    6. using System.Net;
    7. using System.Net.Sockets;
    8.  
    9. public class Client : MonoBehaviour {
    10.  
    11.     private Socket _clientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
    12.     private byte[] _recieveBuffer = new byte[8142];
    13.  
    14.     private void SetupServer()
    15.     {
    16.         try
    17.         {
    18.             _clientSocket.Connect(new IPEndPoint(IPAddress.Loopback,6670));
    19.         }
    20.         catch(SocketException ex)
    21.         {
    22.             Debug.Log(ex.Message);
    23.         }
    24.  
    25.         _clientSocket.BeginReceive(_recieveBuffer,0,_recieveBuffer.Length,SocketFlags.None,new AsyncCallback(ReceiveCallback),null);
    26.  
    27.     }
    28.  
    29.     private void ReceiveCallback(IAsyncResult AR)
    30.     {
    31.         //Check how much bytes are recieved and call EndRecieve to finalize handshake
    32.         int recieved = _clientSocket.EndReceive(AR);
    33.  
    34.         if(recieved <= 0)
    35.             return;
    36.  
    37.         //Copy the recieved data into new buffer , to avoid null bytes
    38.         byte[] recData = new byte[recieved];
    39.         Buffer.BlockCopy(_recieveBuffer,0,recData,0,recieved);
    40.  
    41.         //Process data here the way you want , all your bytes will be stored in recData
    42.  
    43.         //Start receiving again
    44.         _clientSocket.BeginReceive(_recieveBuffer,0,_recieveBuffer.Length,SocketFlags.None,new AsyncCallback(ReceiveCallback),null);
    45.     }
    46.  
    47.     private void SendData(byte[] data)
    48.     {
    49.         SocketAsyncEventArgs socketAsyncData = new SocketAsyncEventArgs();
    50.         socketAsyncData.SetBuffer(data,0,data.Length);
    51.         _clientSocket.SendAsync(socketAsyncData);
    52.     }
    53. }
    54.  
    55.  
    So in async socketing , you would have RecieveCallback , and in the recieve callback you're checking if you actually received data from the server by calling EndAccept method and passing the IAsyncResult parameter.

    After that you copy your recieved buffer into a buffer that has a set value of recieved bytes , this way you avoid null bytes in your buffer.


    Also note that when doing async socketing you're making multiple threads , and cross threads operation are not supported with unity components , so you will have to queue actions to the main thread in order to execute them , or you can make bunch of classes to control the scene that indirectly manipulate unity components.

    Hopefully this will help , hope to hear from you soon!
     
    Last edited: Feb 9, 2014
    Gsiniguez and EnriqueL like this.
  3. chiapekharn

    chiapekharn

    Joined:
    Aug 22, 2012
    Posts:
    11
    Hi Vulegend,

    Thanks! I'll try that out and let you know if it works =)
     
  4. chiapekharn

    chiapekharn

    Joined:
    Aug 22, 2012
    Posts:
    11
    Hi Vuleglend, I've got this respond "No connection could be made because the target machine actively refused it" does that mean my Windows firewall is blocking it?
     
  5. Rupini

    Rupini

    Joined:
    Apr 20, 2014
    Posts:
    4
    Yeah, I have this problem too. Need some help!
     
  6. Olly

    Olly

    Joined:
    Jun 19, 2014
    Posts:
    20
    Doesn't work on Android :-/
     
  7. aalva456

    aalva456

    Joined:
    Jan 25, 2018
    Posts:
    6
    @Vulegend Hi, I need help please. I'm creating a multiplayer game. I have the connection working and the server sending messages to the client, however, for some reason that I don't understand my server does not receive anything from the client.

    I'm gonna upload my code below. I have the server started when clicking the host button, and at the same time, it also starts a client. Some help is highly appreciated.

    Thank you so much
     

    Attached Files: