热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基于Socekt的Unity多人在线聊天系统

先看看效果图以上分别是两个客户端相互通讯的情况的。源码:https:github.comzymixUnity_ChatSystemC#本身对So

先看看效果图



以上分别是两个客户端相互通讯的情况的。


源码:https://github.com/zymix/Unity_ChatSystem


C#本身对Socket拥有着高度的封装,所以搭建这样的一个多人聊天系统是非常容易的事情。这里先提醒几点:

1.关于Unity内部编码问题,Unity在debug阶段时其编码模式是跟操作系统一致的,但是当其发布以后,由于Unity的跨平台性使其编码改变成UTF8的形式,所以无论哪个阶段,都应该注意客户端与服务器段的编码模式一致。

2.关于Scroll View的问题,想滚动条动态的改变滚动长度需要,动态修改Scroll Rect组件的Content对象的RectTransform的deltaSize


剩下的,看注释,算是比较清晰了

客户端代码

using UnityEngine;
using System.Net.Sockets;
using System;

using System.Collections.Generic;
using UnityEngine.UI;
using System.Collections;

public class ChatClient : MonoBehaviour
{
public GameObject content;
public InputField input; //用于发送输入框的信息
public InputField usernameInput;//客户端用户名
public GameObject messageItem;//预制件的宽高
public Button connectButton; //连接按钮

TcpClient client;//客户端
NetworkStream nstream;//网络数据流
string ip = "192.168.10.5";//客户端IP
int port = 10086;//客户端端口
byte[] data;//客户端收发数据
bool isCOnnect= false;

List messageList;//存储接受的消息列表
public int messagesMaxSize = 20;//存储接受的消息列表最大长度
bool isNewMessage = false;//消息更新的标志位
string newMessage;//接受到的最新信息
//预制件的宽高
float height = 0;
float width = 0;
void Start()
{
messageList = new List();
messageList.Capacity = messagesMaxSize;

//获取预设件的宽高
width = messageItem.GetComponent().rect.width;
height = messageItem.GetComponent().rect.height;

//初始化组件
if (cOntent== null)
cOntent= transform.FindChild("Chat View/Viewport/Content").gameObject;
if (input == null)
input = transform.FindChild("InputField").GetComponent();
if (usernameInput == null)
usernameInput = transform.FindChild("UsernameInput").GetComponent();

if (cOnnectButton== null)
cOnnectButton= transform.FindChild("ConnectButton").GetComponent

简单的负责debug的提示信息类

using UnityEngine;
using System.Collections;

public class Info : MonoBehaviour {

public static string debugStr = "";

void OnGUI() {
GUILayout.Label(debugStr);

}
}


服务器端的代码

主程序

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace ChatSystem
{
class Program
{
static void Main(string[] args)
{
//设置监听的端口号
Console.WriteLine("请输入服务器需要监听的端口: ");
string input = Console.ReadLine();
int port = int.Parse(input);
//调用方法启动服务器
Server(port);
}

static void Server(int port)
{
//初始化服务器ip
//IPAddress localAddress = IPAddress.Parse("127.0.0.1");
//设置监听
TcpListener listener = new TcpListener(IPAddress.Any, port);
listener.Start();

//提示信息
Console.WriteLine("{0:HH:mm:ss}->监听端口{1}....", DateTime.Now, port);

//循环等待客户端的连接请求
while(true)
{
ChatServerHandle usr = new ChatServerHandle(listener.AcceptTcpClient());
Console.WriteLine(usr.ip + "加入聊天室");
}
}

}
}


服务器辅助类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

namespace ChatSystem
{
class ChatServerHandle
{
public static Hashtable Clients = new Hashtable();//客户端连接记录表
public TcpClient client;//客户端
public string username;//客户端用户名

public string ip;//客户端IP
public int port;//客户端端口

public byte[] data;//客户端收发数据

bool firstCOnnet= true;

public ChatServerHandle(TcpClient client)
{
this.client = client;

//保存客户端IP和端口
IPEndPoint ipEndPoint = client.Client.RemoteEndPoint as IPEndPoint;
this.ip = ipEndPoint.Address.ToString();
this.port = ipEndPoint.Port;

//初始化收发数据
this.data = new byte[client.ReceiveBufferSize];

//开启异步从客户端获取消息,获取到的数据流存入data,回调ReceiveMessage方法
client.GetStream().BeginRead(data, 0, data.Length, ReceiveMessage, null);

}
//向客户端发送消息
public void SendMessage(string message)
{
try
{
NetworkStream stream;
lock(client.GetStream())
{
stream = client.GetStream();
}
byte[] bytes = Encoding.UTF8.GetBytes(message); //注意Unity发布后程序已UTF8编码
stream.Write(bytes, 0, bytes.Length);
//stream.Flush();
}
catch (Exception e)
{
Console.WriteLine("{0:HH:mm:ss}->[SendMessage]Error: {1}", DateTime.Now, e.Message);
}
}
//从客户端接受到的数据,再广播给所有客户端
public void ReceiveMessage(IAsyncResult ar)
{
try
{
int bytesRead;
lock(client.GetStream())
{
bytesRead = client.GetStream().EndRead(ar);
}
if (bytesRead <1)
{//接收不到任何数据,则删除在客户端连接记录表
Clients.Remove(this.ip);
//向所有客户端广播该用户的下线信息
Broadcast(""+this.username + " 于" + DateTime.Now + " 已下线....");
return;
}
else
{
string recMessage = Encoding.UTF8.GetString(data, 0, bytesRead); //注意Unity发布后程序已UTF8编码
if (firstConnet)
{ //检查是不是同一台电脑重复连接
if(Clients.ContainsKey(this.ip))
return;
//第一次连接,将客户端信息记录入客户端连接记录表中
Clients.Add(this.ip,this);
//获取发送的用户名信息
this.username = recMessage;
//向所有客户端广播该用户的上线信息
Broadcast("" + this.username + " 于" + DateTime.Now+ " 已上线....");
//不在是第一次连接
firstCOnnet= false;
}
else
{
//向所有客户端广播该用户发送的
Broadcast(DateTime.Now + " ->【"+ this.username+"】" + recMessage);
}
//Console.WriteLine(recMessage);
}
lock(client.GetStream())
{
//再次开启异步从服务器获取消息,形成循环
client.GetStream().BeginRead(data, 0, client.ReceiveBufferSize, ReceiveMessage, null);
}
}
catch(Exception e)
{
//删除连接记录
Clients.Remove(this.ip);
//向所有客户端广播该用户的下线信息
Broadcast("" + this.username + " 于" + DateTime.Now + " 已下线....");

Console.WriteLine("{0:HH:mm:ss}->[ReceiveMessage]Error: {1}", DateTime.Now, e.Message);
}
}

//向所有连接到的客户端广播
public void Broadcast(string message)
{
Console.WriteLine(message);
foreach (DictionaryEntry item in Clients)
{
ChatServerHandle c = item.Value as ChatServerHandle;
c.SendMessage(message);
}
}
}
}



推荐阅读
author-avatar
手机用户2502876103
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有