【发布时间】:2017-07-27 12:33:24
【问题描述】:
服务器代码(用 .NET-Core 编写)
using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using Models;
using System.Collections.Generic;
using Newtonsoft.Json;
using Logger;
using System.IO;
public class Server
{
private TcpListener listen;
private int port;
private IPAddress localAddress;
private List<ClientModel> clients;
private NetworkStream stream;
private LoggerDevice logger;
private Dictionary<IPAddress, PlayerModel> lockedPlayers;
private string response;
private bool isLuminol;
private bool isFixative;
/// <summary>
/// Server constructor
/// </summary>
/// <param name="log">Object used to create server logs</param>
public Server(LoggerDevice log)
{
port = 8000;
localAddress = IPAddress.Parse(GetLocalIPAddress());
listen = new TcpListener(localAddress, port);
//listen = new TcpListener(IPAddress.Any, port);
IPEndPoint iep = listen.LocalEndpoint as IPEndPoint;
//localAddress = iep.Address;
clients = new List<ClientModel>();
response = string.Empty;
logger = log;
lockedPlayers = new Dictionary<IPAddress, PlayerModel>();
isLuminol = false;
isFixative = false;
}
/// <summary>
/// Returns a local IP Address of the host
/// </summary>
/// <returns>Local IP Address of the host</returns>
public static string GetLocalIPAddress()
{
var host = Dns.GetHostEntryAsync(Dns.GetHostName());
Console.WriteLine("DNS HOSTNAME: " + Dns.GetHostName());
foreach (var ip in host.Result.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
throw new Exception("Local IP Address Not Found!");
}
/// <summary>
/// Main server thread method
/// Displays current IP Address and connects with clients
/// </summary>
public void ServThread()
{
response = "Adres IP serwera: " + ((IPEndPoint)(listen.LocalEndpoint)).Address.ToString() + '\n';
Console.WriteLine(response);
logger.WriteLine(response);
ClientModel currentClient;
listen.Start();
while (true)
{
Console.WriteLine("Czekam na polaczenie...");
currentClient = new ClientModel();
currentClient.clientSender = listen.AcceptTcpClientAsync().Result;
ThreadPool.QueueUserWorkItem(HandleClient, currentClient);
}
}
/// <summary>
/// Method creating and configuring a new instance of ClientModel
/// Assigns new ClientModel.Id when needed and matches ClientModel with the assigned player if reconnecting
/// </summary>
/// <param name="c">Client to be handled (explicitly converted to ClientModel in the method)</param>
private void HandleClient(object c)
{
ClientModel currentClient = (ClientModel)c;
response = "Polaczono!";
Console.WriteLine(response);
logger.WriteLine(response);
CommunicationModel currentCommunication = new CommunicationModel();
Random rand = new Random();
string currentID;
if (string.IsNullOrEmpty(currentClient.Id))
{
Guid g = Guid.NewGuid();
currentID = g.ToString();
currentClient.Id = g.ToString();
response = "Nadano nowe ID: " + currentClient.Id;
Console.WriteLine(response);
logger.WriteLine(response);
clients.Add(currentClient);
}
currentID = currentClient.Id;
currentCommunication.Id = currentID;
IPEndPoint ipep = (IPEndPoint)currentClient.clientSender.Client.RemoteEndPoint;
IPAddress ipa = ipep.Address;
if (lockedPlayers.ContainsKey(ipa))
{
CommunicationModel mess = new CommunicationModel();
string currentId = currentClient.Id;
response = "Dolaczyl gracz ze zwiazanym playerem (ID: "+currentID+")";
Console.WriteLine(response);
logger.WriteLine(response);
currentClient.clientSender.GetStream();
currentClient.clientSender.GetStream().Flush();
mess.Id = currentId;
mess.Message = JsonConvert.SerializeObject(lockedPlayers[ipa]);
mess.Type = 101;
string comMess = JsonConvert.SerializeObject(mess);
byte[] data = UTF8Encoding.UTF8.GetBytes(comMess);
currentClient.clientSender.GetStream().Write(data, 0, data.Length);
response = "Pomyslnie przypisano gracza z ID: "+currentId+"do jego domyslnego playera";
Console.WriteLine(response);
logger.WriteLine(response);
}
servMessReceived(clients.Find(x => x.Id.Equals(currentID)));
}
public class ItemModel
{
public string Name = "";
public bool Have;
}
ServThread 是从其他脚本启动的。
客户端代码(Unity中的脚本)
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Models;
using UnityEngine;
using System.Collections;
class Client : MonoBehaviour
{
TcpClient clientSocket;
CommunicationModel mess;
IPEndPoint end;
PlayerNetworkController player;
NetworkStream clientStream;
int state = 0;
byte[] rec = new byte[100000];
int bytes;
bool reading;
private void Start()
{
//clientSocket = new TcpClient(AddressFamily.InterNetwork);
mess = new CommunicationModel();
player = IOC.Resolve<WorshipGameManager>("WorshipGameManager").playerNetworkController;
bool reading = true;
}
private void Update()
{
}
public void ConnectEnd(string ip)
{
end = new IPEndPoint(IPAddress.Parse(ip), 8000);
clientSocket = new TcpClient(AddressFamily.InterNetwork);
clientSocket.Connect(end.Address, end.Port);
clientStream = clientSocket.GetStream();
StartCoroutine(ReceiveMessage());
}
private IEnumerator ReceiveMessage()
{
//Odczytywanie odpowiedzi
//clientStream = clientSocket.GetStream();
float timePassed = 0.0f;
rec = new byte[100000];
while (true)
{
if (timePassed > 5.0f)
timePassed = 0.0f;
timePassed += Time.deltaTime;
clientStream.BeginRead(rec, 0, rec.Length, new AsyncCallback(this.HandleMessage), this);
yield return new WaitWhile(() => reading == true || timePassed >= 5.0f);
}
}
public void HandleMessage(IAsyncResult ar)
{
reading = true;
bytes = clientStream.EndRead(ar);
clientStream.Flush();
if (bytes > 0)
{
string responseMessage = UTF8Encoding.UTF8.GetString(rec, 0, bytes);
Debug.Log("Message received: " + responseMessage);
CommunicationModel cm = JsonUtility.FromJson<CommunicationModel>(responseMessage);
Debug.Log("cm.Name: " + cm.Name);
Debug.Log("cm.Type: " + cm.Type);
Debug.Log("cm.Id: " + cm.Id);
Debug.Log("cm.Message: " + cm.Message);
if (player == null)
player = IOC.Resolve<WorshipGameManager>("WorshipGameManager").playerNetworkController;
switch (cm.Type)
{
case 100:
player.OnConnectToServer(""); break;
case 101:
player.GetPlayerData(cm); break;
case 111:
player.GetItemFromServer(cm); break;
case 112:
player.SetLuminolActive(cm); break;
case 113:
player.SetItemFromServer(cm); break;
case 114:
player.SetType(cm); break;
}
}
reading = false;
}
public void SendMessageAsync(short type, string message)
{
{
byte[] rec = new byte[100000];
mess.Id = "0";
mess.Type = type;
mess.Message = message;
rec = Encoding.ASCII.GetBytes(JsonUtility.ToJson(mess));
NetworkStream clientStream = clientSocket.GetStream();
clientStream.Write(rec, 0, rec.Length);
clientStream.Flush();
message = Console.ReadLine();
}
}
public void OnServerConnect()
{
Debug.Log("OnServerConnect");
player.OnConnectToServer("");
}
}
这是管理与服务器的所有连接的脚本。
在连接之前,播放器会看到一个菜单,其中包含一个 IP 输入字段和一个连接按钮,该按钮从其他脚本触发 OnConnectToServer(),该脚本从该脚本触发 ConnectEnd。
当我在编辑器中运行游戏时,服务器连接正常。只有当我构建应用程序并在我的 Android 设备上播放它时,它才无法连接(ServerApp 没有显示适当的消息)
我已经尝试在笔记本电脑上禁用防火墙,以管理员身份运行服务器并在连接到不同网络时测试这两个应用程序;
这与我计算机上的 Unity 构建过程或网络设置有关吗?或者我的脚本有问题?
编辑: LoggerDevice、ItemModel、CommunicationModel 都是包含在不同脚本中的类,它们不包含直接连接到服务器的方法
【问题讨论】:
标签: c# android unity3d networking .net-core