Шлифование данных с TCP-сервера C # на подключенный клиент вне прослушивающего потока - PullRequest
1 голос
/ 12 ноября 2011

Я пишу простой Tcp-сервер в Unity, и к нему подключается мое Flash-приложение.Я нашел отличный учебник по многопоточному Tcp-серверу в сети, и мое флеш-приложение прекрасно к нему подключается.Однако я не могу отправить данные за пределы потока прослушивания подключенному клиенту.Я попытался создать глобальную ссылку на Tcpclient, полученную внутри потока.Однако эта ссылка (sclient) работает только внутри слушающего потока, печатая Null на консоли за пределами потока.Должно быть что-то, что я могу сделать, чтобы сохранить ссылку на TCP-клиент для последующего использования или получить доступ к нему вне потока блока.Пожалуйста, помогите!

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
    }
}

Ответы [ 2 ]

0 голосов
/ 16 февраля 2012

Где метод, вызывающий Update?

Похоже, ни один клиент еще не был подключен, когда вы вызываете его.

0 голосов
/ 12 ноября 2011

В целом, лучше избегать синхронных методов сокета, сетевого потока, следует использовать xxxxAsync (в сокете есть такие методы) или методы BeginXXX.Это дает вам высокую производительность с подсчетом подключенных клиентов.Хорошо, теперь о синхронном ... вы должны создать новый поток для каждого нового подключенного клиента и начать обработку сеанса в этом потоке.Я предлагаю вам создать некоторый класс сеанса для подключенного клиента и всю обработку в этом классе.

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. 
    }
}

Просто вызовите экземпляр экземпляра класса сеанса (Your_Session session = new YourSession ...) в методе ListenForClients и вызовите ThreadPool.QueueUserWorkItem (new WaitCallback (session.Start));начать обработку сеанса.

...