1

I am writing a simple Tcp server in Unity and have my Flash application connects to it. I found a great tutorial on threaded Tcp server online, and my flash app connects to it nicely. However, I am not able to send data outside of the listening thread to the connected client. I tried to create a global reference of the Tcpclient obtained inside of the thread. However, that reference (sclient) only works inside of the listening thread, printed Null to console outside of the thread. There must be something I can do to retain the TCP client reference for later use or access it from outside of block thread. Please help!

using UnityEngine;
using System.Collections;
using System;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;

public class TCPServer: MonoBehaviour
{
    private TcpListener tcpListener;
    private Thread listenThread;
    private TcpClient sclient;

    public float fireRate = 0.5F;
    private float nextFire = 0.0F;

public TCPServer()
{
    IPAddress localAddress = IPAddress.Parse("127.0.0.1");
    this.tcpListener = new TcpListener(localAddress, 9001);
    this.listenThread = new Thread(new ThreadStart(ListenForClients));
    this.listenThread.Start();
}

public void ListenForClients()
{
  this.tcpListener.Start();

  while (true)
{
    //blocks until a client has connected to the server
    sclient = this.tcpListener.AcceptTcpClient();

    print(sclient);//print "System.Net.Sockets.TcpClient" in console

    this.sMessage("Can you hear me now?");//this one works fine
}       
}

public void sMessage(String m){
    print(cStream); //print "Null" to console
    NetworkStream clientStream = sclient.GetStream();
    ASCIIEncoding encoder = new ASCIIEncoding();
    byte[] buffer = encoder.GetBytes(m);

    print("Received Connection from " + tcpClient.Client.RemoteEndPoint );
    print("Sending message..");
    print(clientStream.CanWrite);//returns true in console

    clientStream.Write(buffer, 0 , buffer.Length);
    clientStream.WriteByte (0);
    clientStream.Flush();
}

void Update() {
    if (Input.GetButton("Fire1") && Time.time > nextFire) {
        nextFire = Time.time + fireRate;
        this.sMessage("BOOM BOOM");//this one won't work. keep saying sclient is null
    }
}
Lex Li
  • 60,503
  • 9
  • 116
  • 147
Ghettokon
  • 63
  • 8

2 Answers2

0

In general it's besit if you avoid synchronous methods of socket,networkstream, you should use xxxxAsync(socket has such methods) or BeginXXX methods. This gives you high performance with count of connected clients. Ok now about synchornous ... you should create new thread for each new connected client and start session processing on that thread. I suggest you to make some session class for connected client, and all processing in that class.

public class Your_Session
{
    private TcpClient m_pClient = null;

    public Your_Session(TcpClient client)
    {
        mpClient = client; // Assign client to mpClient
    }

    internal void Start(Object state)
    {
        // NOTE: call this Start method: 
        // ThreadPool.QueueUserWorkItem(new WaitCallback(session.Start));


        // Start your session processing here. This method is called from threapool thread. 
    }
}

Just call create session class instance(Your_Session session = new YourSession ...) in ListenForClients method and call ThreadPool.QueueUserWorkItem(new WaitCallback(session.Start)); to start session processing.

Johnaudi
  • 257
  • 1
  • 23
Ivar
  • 491
  • 3
  • 2
  • Hi Ivar Thanks for your solution I will give it a shot, I have 0 experience in thread/session programming. Before I get into it in a sec, once I start the session how do I send data to client? for example, I have a external value that is constantly being updated and sent to the client, how do I do that in this session? – Ghettokon Nov 13 '11 at 01:57
  • I don't get exactly what you mean ... . – Ivar Nov 18 '11 at 11:43
0

Where is the method that calls Update?

Sounds like no client has been connected yet when you invoke it.

jgauffin
  • 99,844
  • 45
  • 235
  • 372