Unity實(shí)現(xiàn)局域網(wǎng)聊天室功能
基于Unity實(shí)現(xiàn)一個(gè)簡(jiǎn)單的局域網(wǎng)聊天室,供大家參考,具體內(nèi)容如下
學(xué)習(xí)Unity有一點(diǎn)時(shí)間了,之前學(xué)的都是做客戶端的一些內(nèi)容,現(xiàn)在開始學(xué)習(xí)聯(lián)網(wǎng)。我的這個(gè)是在觀看了 Siki 的教學(xué)內(nèi)容來做的,也有自己的一點(diǎn)點(diǎn)小小的改動(dòng)在里面。純粹用于練手了。
因?yàn)楸救艘彩切“滓幻?,所以,有錯(cuò)誤的地方或者更好的實(shí)現(xiàn)方法,也希望有大神能幫忙指正,多謝!
整體過程分為兩部分:構(gòu)建服務(wù)端、構(gòu)建客戶端。
服務(wù)端:
大概思路:
1. 聲明Socket連接以及綁定IP和端口,這里面使用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace ServerApplication
{
class Program
{
public static string IP;
public static int Port;
static List<Client> clientList = new List<Client>();
static Socket serverSocket;
static void Main(string[] args)
{
//綁定IP和端口
BindIPAndPort();
//
while (true)
{
Socket clientSocket = serverSocket.Accept();
Client client = new Client(clientSocket);
clientList.Add(client);
Console.WriteLine("一臺(tái)主機(jī)進(jìn)入連接");
}
}
/// <summary>
/// 廣播數(shù)據(jù)
/// </summary>
public static void BroadcostMSG(string s)
{
List<Client> NotConnectedList = new List<Client>();
foreach (var item in clientList)
{
if(item.IsConnected)
{
item.SendMSG(s);
}
else
{
NotConnectedList.Add(item);
}
}
foreach (var item in NotConnectedList)
{
clientList.Remove(item);
}
}
/// <summary>
/// 綁定IP和端口
/// </summary>
public static void BindIPAndPort()
{
//創(chuàng)建一個(gè)serverSocket
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//聲明IP和端口
Console.WriteLine("輸入IP地址:");
IP = Console.ReadLine();
string ipStr = IP;
Console.WriteLine("請(qǐng)輸入端口:");
Port = int.Parse(Console.ReadLine());
int port = Port;
IPAddress serverIp = IPAddress.Parse(ipStr);
EndPoint serverPoint = new IPEndPoint(serverIp, port);
//socket和ip進(jìn)行綁定
serverSocket.Bind(serverPoint);
//監(jiān)聽最大數(shù)為100
serverSocket.Listen(100);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Threading;
namespace ServerApplication
{
class Client
{
public Socket clientSocket;
//聲明一個(gè)線程用于接收信息
Thread t;
//接收信息所用容器
byte[] data = new byte[1024];
//構(gòu)造函數(shù)
public Client(Socket s)
{
clientSocket = s;
t = new Thread(ReceiveMSG);
t.Start();
}
/// <summary>
/// 接收數(shù)據(jù)
/// </summary>
void ReceiveMSG()
{
while(true)
{
if (clientSocket.Poll(10,SelectMode.SelectRead))
{
break;
}
data = new byte[1024];
int length = clientSocket.Receive(data);
string message = Encoding.UTF8.GetString(data, 0, length);
Program.BroadcostMSG(message);
Console.WriteLine("收到消息:" + message);
}
}
/// <summary>
/// 發(fā)送數(shù)據(jù)
/// </summary>
/// <param name="s"></param>
public void SendMSG(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);
}
//判斷此Client對(duì)象是否在連接狀態(tài)
public bool IsConnected
{
get { return clientSocket.Connected; }
}
}
}
客戶端:
a.UI界面
UI界面是使用UGUI實(shí)現(xiàn)的
登錄用戶可以自己取名進(jìn)行登錄(發(fā)言時(shí)用于顯示),使用時(shí)需要輸入服務(wù)端的IP地址和端口號(hào)

下面是聊天室的頁面,在輸入框內(nèi)輸入要發(fā)送的消息,點(diǎn)擊Send,將信息發(fā)送出去

這是服務(wù)端的信息

b.關(guān)于客戶端的腳本
(1)這是ClientManager,負(fù)責(zé)與服務(wù)端進(jìn)行連接,通信
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using System.Net;
using System.Text;
using UnityEngine.UI;
using System.Threading;
public class ClientManager : MonoBehaviour
{
//ip:192.168.1.7
public string ipAddressstr;
public int port;
public Text ipTextToShow;
//Socket
private Socket ClientServer;
//文本輸入框
public InputField inputTxt;
public string inputMSGStr;
//接收
Thread t;
public Text receiveTextCom;
public string message;
// Use this for initialization
void Start()
{
ipTextToShow.text = ipAddressstr;
// ConnectedToServer();
}
// Update is called once per frame
void Update()
{
if (message != null && message != "")
{
receiveTextCom.text = receiveTextCom.text + "\n" + message;
message = "";
}
}
/// <summary>
/// 連接服務(wù)器
/// </summary>
public void ConnectedToServer()
{
ClientServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//聲明IP地址和端口
IPAddress ServerAddress = IPAddress.Parse(ipAddressstr);
EndPoint ServerPoint = new IPEndPoint(ServerAddress, port);
ipAddressstr = IpInfo.ipStr;
port = IpInfo.portStr;
//開始連接
ClientServer.Connect(ServerPoint);
t = new Thread(ReceiveMSG);
t.Start();
}
/// <summary>
/// 接收消息
/// </summary>
/// <returns>“string”</returns>
void ReceiveMSG()
{
while (true)
{
if (ClientServer.Connected == false)
{
break;
}
byte[] data = new byte[1024];
int length = ClientServer.Receive(data);
message = Encoding.UTF8.GetString(data, 0, length);
//Debug.Log("有消息進(jìn)來");
}
}
/// <summary>
/// 發(fā)送string類型數(shù)據(jù)
/// </summary>
/// <param name="input"></param>
public void SendMSG()
{
Debug.Log("button Clicked");
//message = "我:" + inputTxt.text;
inputMSGStr = inputTxt.text;
byte[] data = Encoding.UTF8.GetBytes(IpInfo.name+":"+inputMSGStr);
ClientServer.Send(data);
}
private void OnDestroy()
{
ClientServer.Shutdown(SocketShutdown.Both);
ClientServer.Close();
}
private void OnApplicationQuit()
{
OnDestroy();
}
}
(2)SceneManager,用于場(chǎng)景切換,這里只是利用GameObject進(jìn)行SetActive()來實(shí)現(xiàn),并不是創(chuàng)建了單獨(dú)的Scene進(jìn)行管理。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SceneManager : MonoBehaviour {
public GameObject loginPanel;
public GameObject communicatingPanel;
// Use this for initialization
public void OnSwitch()
{
loginPanel.SetActive(false);
communicatingPanel.SetActive(true);
}
}
(3)LogInPanel和IPInfo,一個(gè)掛載在登錄界面上,一個(gè)是數(shù)據(jù)模型,用于存儲(chǔ)數(shù)據(jù)。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LogInPanel : MonoBehaviour {
public Text nameInputTxt;
public Text ipInputTxt;
public Text portInputTxt;
//private string name;
//private string ipStr;
//private string portStr;
public void OnLogInClick()
{
IpInfo.name = nameInputTxt.text;
IpInfo.ipStr = ipInputTxt.text;
IpInfo.portStr = int.Parse(portInputTxt.text);
}
}
public static class IpInfo {
public static string name;
public static string ipStr;
public static int portStr;
}
總結(jié):第一次寫學(xué)習(xí)博,還有很多地方要學(xué)習(xí)啊。
留待解決的問題:此聊天室只能用于局域網(wǎng)以內(nèi),廣域網(wǎng)就無法實(shí)現(xiàn)通信了,還要看看怎么實(shí)現(xiàn)遠(yuǎn)程的一個(gè)通信,不然這個(gè)就沒有存在的意義了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C# InitializeComponent()方法案例詳解
這篇文章主要介紹了C# InitializeComponent()方法案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
c# 閉包的相關(guān)知識(shí)以及需要注意的地方
這篇文章主要介紹了c# 閉包的相關(guān)知識(shí)以及需要注意的地方,文中講解非常細(xì)致,代碼幫助大家理解和學(xué)習(xí),感興趣的朋友可以參考下2020-06-06
c#反射機(jī)制學(xué)習(xí)和利用反射獲取類型信息
反射(Reflection)是.NET中的重要機(jī)制,通過放射,可以在運(yùn)行時(shí)獲得.NET中每一個(gè)類型(包括類、結(jié)構(gòu)、委托、接口和枚舉等)的成員,包括方法、屬性、事件,以及構(gòu)造函數(shù)等。還可以獲得每個(gè)成員的名稱、限定符和參數(shù)等。有了反射,即可對(duì)每一個(gè)類型了如指掌。如果獲得了構(gòu)造函數(shù)的信息,即可直接創(chuàng)建對(duì)象,即使這個(gè)對(duì)象的類型在編譯時(shí)還不知道2014-01-01
C#實(shí)現(xiàn)將HTML轉(zhuǎn)換成純文本的方法
這篇文章主要介紹了C#實(shí)現(xiàn)將HTML轉(zhuǎn)換成純文本的方法,基于自定義類實(shí)現(xiàn)文本轉(zhuǎn)換功能,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07

