将数据从 C# TCP 服务器发送到侦听线程外部的连接客户端

发布于 2024-12-15 16:05:29 字数 1935 浏览 0 评论 0原文

我正在 Unity 中编写一个简单的 Tcp 服务器,并将我的 Flash 应用程序连接到它。我在网上找到了一个关于线程 Tcp 服务器的很棒的教程,我的 Flash 应用程序可以很好地连接到它。但是,我无法将侦听线程之外的数据发送到连接的客户端。我尝试创建在线程内部获得的 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
    }
}

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

握住我的手 2024-12-22 16:05:29

调用Update的方法在哪里?

听起来当您调用它时还没有连接客户端。

Where is the method that calls Update?

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

绅士风度i 2024-12-22 16:05:29

一般来说,如果你避免socket、networkstream的同步方法,你应该使用xxxxAsync(socket有这样的方法)或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. 
    }
}

只需在 ListenForClients 方法中调用 create session class instance(Your_Session session = new YourSession ...) 并调用 ThreadPool.QueueUserWorkItem(new WaitCallback(session.Start));开始会话处理。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文