广告位联系
返回顶部
分享到

Unity实现局域网聊天室功能

C语言 来源:转载 作者:秩名 发布时间:2021-10-10 17:35:30 人浏览
摘要

学习Unity有一点时间了,之前学的都是做客户端的一些内容,现在开始学习联网。我的这个是在观看了 Siki 的教学内容来做的,也有自己的一点点小小的改动在里面。纯粹用于练手了。 因为本人也是小白一枚,所以,有错误的地方或者更好的实现方法,也希望有大神

学习Unity有一点时间了,之前学的都是做客户端的一些内容,现在开始学习联网。我的这个是在观看了 Siki 的教学内容来做的,也有自己的一点点小小的改动在里面。纯粹用于练手了。

因为本人也是小白一枚,所以,有错误的地方或者更好的实现方法,也希望有大神能帮忙指正,多谢!

整体过程分为两部分:构建服务端、构建客户端。

服务端:

大概思路:

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("一台主机进入连接");
            }
        }



        /// <summary>
        /// 广播数据
        /// </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()
        {

            //创建一个serverSocket
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //声明IP和端口
            Console.WriteLine("输入IP地址:");
            IP = Console.ReadLine();
            string ipStr = IP;


            Console.WriteLine("请输入端口:");
            Port = int.Parse(Console.ReadLine());
            int port = Port;

            IPAddress serverIp = IPAddress.Parse(ipStr);
            EndPoint serverPoint = new IPEndPoint(serverIp, port);

            //socket和ip进行绑定
            serverSocket.Bind(serverPoint);

            //监听最大数为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;
        //声明一个线程用于接收信息
        Thread t;
        //接收信息所用容器
        byte[] data = new byte[1024];

       //构造函数
        public Client(Socket s)
        {
            clientSocket = s;
            t = new Thread(ReceiveMSG);
            t.Start();
        }

        /// <summary>
        /// 接收数据
        /// </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>
        /// 发送数据
        /// </summary>
        /// <param name="s"></param>
       public void SendMSG(string message)
        {
            byte[] data = Encoding.UTF8.GetBytes(message);
            clientSocket.Send(data);
        }



        //判断此Client对象是否在连接状态
        public bool IsConnected
        {
            get { return clientSocket.Connected; }
        }

    }
}

客户端:

a.UI界面

UI界面是使用UGUI实现的
登录用户可以自己取名进行登录(发言时用于显示),使用时需要输入服务端的IP地址和端口号

下面是聊天室的页面,在输入框内输入要发送的消息,点击Send,将信息发送出去

这是服务端的信息

b.关于客户端的脚本

(1)这是ClientManager,负责与服务端进行连接,通信

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>
    /// 连接服务器
    /// </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("有消息进来");

        }

    }


    /// <summary>
    /// 发送string类型数据
    /// </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,用于场景切换,这里只是利用GameObject进行SetActive()来实现,并不是创建了单独的Scene进行管理。
 
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,一个挂载在登录界面上,一个是数据模型,用于存储数据。

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;

}

总结:第一次写学习博,还有很多地方要学习啊。

留待解决的问题:此聊天室只能用于局域网以内,广域网就无法实现通信了,还要看看怎么实现远程的一个通信,不然这个就没有存在的意义了。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/weixin_40271181/article/details/78961387
相关文章
  • C++中类的六大默认成员函数的介绍

    C++中类的六大默认成员函数的介绍
    一、类的默认成员函数 二、构造函数Date(形参列表) 构造函数主要完成初始化对象,相当于C语言阶段写的Init函数。 默认构造函数:无参的构
  • C/C++实现遍历文件夹最全方法总结介绍

    C/C++实现遍历文件夹最全方法总结介绍
    一、filesystem(推荐) 在c++17中,引入了文件系统,使用起来非常方便 在VS中,可以直接在项目属性中调整: 只要是C++17即以上都可 然后头文件
  • C语言实现手写Map(数组+链表+红黑树)的代码

    C语言实现手写Map(数组+链表+红黑树)的代码
    要求 需要准备数组集合(List) 数据结构 需要准备单向链表(Linked) 数据结构 需要准备红黑树(Rbtree)数据结构 需要准备红黑树和链表适配策略
  • MySQL系列教程之使用C语言来连接数据库

    MySQL系列教程之使用C语言来连接数据库
    写在前面 知道了 Java中使用 JDBC编程 来连接数据库了,但是使用 C语言 来连接数据库却总是连接不上去~ 立即安排一波使用 C语言连接 MySQL数
  • 基于C语言实现简单学生成绩管理系统

    基于C语言实现简单学生成绩管理系统
    一、系统主要功能 1、密码登录 2、输入数据 3、查询成绩 4、修改成绩 5、输出所有学生成绩 6、退出系统 二、代码实现 1 2 3 4 5 6 7 8 9 10 11
  • C语言实现共享单车管理系统

    C语言实现共享单车管理系统
    1.功能模块图; 2.各个模块详细的功能描述。 1.登陆:登陆分为用户登陆,管理员登陆以及维修员登录,登陆后不同的用户所执行的操作
  • C++继承与菱形继承的介绍

    C++继承与菱形继承的介绍
    继承的概念和定义 继承机制是面向对象程序设计的一种实现代码复用的重要手段,它允许程序员在保持原有类特性的基础上进行拓展,增加
  • C/C++指针介绍与使用介绍

    C/C++指针介绍与使用介绍
    什么是指针 C/C++语言拥有在程序运行时获得变量的地址和操作地址的能力,这种用来操作地址的特殊类型变量被称作指针。 翻译翻译什么
  • C++进程的创建和进程ID标识介绍
    进程的ID 进程的ID,可称为PID。它是进程的唯一标识,类似于我们的身份证号是唯一标识,因为名字可能会和其他人相同,生日可能会与其他
  • C++分析如何用虚析构与纯虚析构处理内存泄漏

    C++分析如何用虚析构与纯虚析构处理内存泄漏
    一、问题引入 使用多态时,如果有一些子类的成员开辟在堆区,那么在父类执行完毕释放后,没有办法去释放子类的内存,这样会导致内存
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计