【发布时间】:2019-01-11 18:11:11
【问题描述】:
我正在从事一个学术项目,该项目包括从传统的 Android 应用程序控制在 Unity3D 中创建的模拟环境。我已经在 Unity 中创建了场景并且移动应用程序已经完全完成,我的问题在于连接。我选择使用套接字是因为它简单。我设法通过常规的 Sockets 将应用程序连接到用 C# 编写的服务器,我知道可以发送信息,但是当我在 Unity 中实现它时,一切都失败了,所以我决定在 Unity/C 中使用 TCP Listener 而不是 Sockets #(客户端Android仍然使用通过Sockets的常规TCP连接),实际上应用程序连接但没有信息传输,因为Unity控制台抛出错误说:ObjectDisposedException: Can not access to disposed object.
Object name: 'System.Net.Sockets.TcpClient'.(错误出现在行号中56:stream = client.tcp.GetStream ();) 主要目标是获取信息流,这些信息流可以用以下形式表示:"1: 0: 1: 0" 并能够对该字符串进行拆分,并根据该值更改灯泡的状态或其他元素,但我需要基本的东西:建立连接流。我不是 C# 方面的专家,更不会使用 Unity,我对设计真的不太了解,但我想做一个创新的工作,希望有人能指导我。
PD:使用 Android Java 客户端的 C# Socket(尚无 Unity)服务器: ![1] https://imgur.com/a/HuNcDC3
//这是我的 Unity3D/C# 服务器:
public class SocketManager : MonoBehaviour
{
private List<ServerClient> connectedClients;
private List<ServerClient> disconectedClients;
private TcpListener server;
private string data;
private NetworkStream stream;
private StreamReader stremaReader;
private bool serverStarted;
public int socketPort = 7691;
private void Start()
{
connectedClients = new List<ServerClient>();
disconectedClients = new List<ServerClient>();
try
{
server = new TcpListener(IPAddress.Parse("192.168.1.64"), socketPort);
server.Start();
serverListening();
serverStarted = true;
Debug.Log("Server started. Port: " + socketPort.ToString());
}
catch (Exception ex)
{
Debug.Log("Server socket error: " + ex);
}
}
private void Update()
{
if (!serverStarted)
return;
foreach (ServerClient client in connectedClients)
{
if (IsConnected(client.tcp))
{
client.tcp.Close();
disconectedClients.Add(client);
continue;
}
else
{
stream = client.tcp.GetStream();
if (stream.DataAvailable)
{
this.stremaReader = new StreamReader(stream, true);
data = stremaReader.ReadLine();
if (data != null)
OnIcomingData(client, data);
}
}
}
}
private void OnIcomingData(ServerClient client, string data)
{
Debug.Log(client.clientName + ": " + data);
}
private bool IsConnected(TcpClient tcp)
{
try
{
if (tcp != null && tcp.Client != null && tcp.Client.Connected)
{
if (tcp.Client.Poll(0, SelectMode.SelectRead))
{
return !(tcp.Client.Receive(new byte[1], SocketFlags.Peek) == 0);
}
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
private void serverListening()
{
server.BeginAcceptTcpClient(AcceptTcpClient, server);
}
private void AcceptTcpClient(IAsyncResult asyncResult)
{
TcpListener tcplistener = (TcpListener)asyncResult.AsyncState;
connectedClients.Add(new ServerClient(tcplistener.EndAcceptTcpClient(asyncResult)));
serverListening();
}
}
public class ServerClient
{
public TcpClient tcp;
public string clientName;
public ServerClient(TcpClient tcp)
{
this.tcp = tcp;
this.clientName = "Android";
}
}
// 这是我的 Android/Java 客户端:
public class SocketThread extends Thread {
private Socket adviser;
private DataOutputStream dataOut;
@Override
public void run() {
super.run();
Log.e("Status:", "Thread started");
try {
adviser = new Socket("192.168.1.64", 7691);
dataOut = new DataOutputStream(adviser.getOutputStream());
} catch (IOException ex) {
Logger.getLogger(SocketThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sendCommand(String text) {
try {
dataOut.writeUTF(text);
Log.e("Sended Text: ", text);
} catch (IOException ex) {
Logger.getLogger(SocketThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
【问题讨论】:
-
在你的 foreach 循环中,你得到一个 if 语句
if (IsConnected(client.tcp)),如果它是真的(客户端已连接),你通过调用client.tcp.Close();关闭连接。这是故意的吗?还是您的意思是!IsConnected?如果客户端未连接(因为您关闭了连接,它将在下一次迭代中)您尝试使用stream = client.tcp.GetStream();获取流,因为流已关闭,所以这是不可能的。所以我认为if (!IsConnected(client.tcp))应该可以解决问题? -
remy_rm,是的,你说得对,我非常感谢你的帮助,我不再有错误,但是,我没有显示我从手机发送的字符串,我知道两个设备都已连接,但服务器没有获取信息,我正在通过调试进行一些检查。 ..