美文网首页
Unity网络编程(二)TCP 1V1聊天室

Unity网络编程(二)TCP 1V1聊天室

作者: 罗卡恩 | 来源:发表于2019-12-14 20:46 被阅读0次

服务端

先做个同步的

// 这种通常用于socket的复制
public Socket(SocketInformation socketInformation);
// 后面两种通常用于新创建的socket
public Socket(SocketType socketType, ProtocolType protocolType);
//指定 Socket 类的实例可以使用的寻址方案(通常IPv4 也有IPv6)  Socket类的实例表示的套接字类型  指定 Socket 类支持的协议
public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType);

搭配不当就出异常
常用组合

// Udp通信
Socket socket = new Socket(SocketType.Dgram, ProtocolType.Udp);
// Tcp通信
Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

用VS窗口控制台

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;


namespace TalkRoomTCP
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建socket using 代替Close 用完不关闭会占用端口
            using (Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp))
            {
                //绑定IP 端口号
                //IPAddress.Any:相当于"0.0.0.0"的IP地址侦听本地所有网络接口上的客户端活动 有几个侦听几个
                //IPAddress.Broadcast:相当于"255.255.255.255"的IP地址,通常用于Udp的数据包广播。
                //IPAddress.Loopback:相当于"127.0.0.1"的IP地址,用于指代本机。监听"127.0.0.1"时,只能从本机连接到服务端。
                socket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9999));
                //开启监听 参数是最大接受队列的长度 多于这个就只响应100个 其他拒绝
                socket.Listen(100);

                //accept客户端同步连接 如果客户端不连接,服务器程序阻塞(挂起)这个位置
                using (var clientSocket = socket.Accept())
                {
                    //客户端接收消息 如果客户端不发送数据 服务器程序阻塞(挂起)这个位置
                    var buffer = new byte[1024];
                    int length = clientSocket.Receive(buffer);

                    Console.WriteLine($"接收到客户端消息:{Encoding.UTF8.GetString(buffer)}");
                    //接受的消息再发回去
                    clientSocket.Send(buffer);
                }
            }
            // 接收一个键盘输入的字符,目的是不让命令行自动关闭
            Console.ReadKey();
        }
    }
}


客户端

unity创建个项目

/**
 *Copyright(C) 2019 by #COMPANY#
 *All rights reserved.
 *FileName:     #SCRIPTFULLNAME#
 *Author:       #AUTHOR#
 *Version:      #VERSION#
 *UnityVersion:#UNITYVERSION#
 *Date:         #DATE#
 *Description:   
 *History:
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class TalkClient : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
        //连接服务器
        socket.Connect("127.0.0.1", 9999);
        //发送数据
        socket.Send(Encoding.UTF8.GetBytes("你好"));

        //接受数据
        var buffer = new byte[1024];
        int length = socket.Receive(buffer);
        print(Encoding.UTF8.GetString(buffer));
    }
}

先运行服务器 再拖动脚本到物体上运行启动客户端

image.png
image.png

然后客户端改个界面


image.png

text差不多大就行

/**
 *Copyright(C) 2019 by #COMPANY#
 *All rights reserved.
 *FileName:     #SCRIPTFULLNAME#
 *Author:       #AUTHOR#
 *Version:      #VERSION#
 *UnityVersion:#UNITYVERSION#
 *Date:         #DATE#
 *Description:   
 *History:
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine.UI;
public class TalkClient : MonoBehaviour
{
    public InputField input;
    public Text text;
    public Button btn;
    byte[] buffer = new byte[1024];
    Socket socket;
    // Start is called before the first frame update
    void Start()
    {
        socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
        //连接服务器
        socket.Connect("127.0.0.1", 9999);
        btn.onClick.AddListener(Send);
    }
    void Send()
    {
        //发送数据
        socket.Send(Encoding.UTF8.GetBytes(input.text));

        //接受数据
        int length = socket.Receive(buffer);
        text.text += Encoding.UTF8.GetString(buffer, 0, length) + "\n";

    }
}
image.png

改为异步服务器

一般项目都是源源不断请求的
所以要开线程异步完成
socket封装的有方便我们写了
先升级服务端
每次Accept 或者Receive 关闭之后都要重新调用

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;


namespace TalkRoomTCP
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建socket using 代替Close 用完不关闭会占用端口
            Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

            //绑定IP 端口号
            //IPAddress.Any:相当于"0.0.0.0"的IP地址侦听本地所有网络接口上的客户端活动 有几个侦听几个
            //IPAddress.Broadcast:相当于"255.255.255.255"的IP地址,通常用于Udp的数据包广播。
            //IPAddress.Loopback:相当于"127.0.0.1"的IP地址,用于指代本机。监听"127.0.0.1"时,只能从本机连接到服务端。
            socket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9999));
            //开启监听 参数是最大接受队列的长度 多于这个就只响应100个 其他拒绝
            socket.Listen(100);

            //开启异步 第二个参数用于传递一些数据
            socket.BeginAccept(AcceptCallBack, socket);
            Console.WriteLine("服务器启动");
            // 接收一个键盘输入的字符,目的是不让命令行自动关闭
            Console.ReadKey();
        }

        private static void AcceptCallBack(IAsyncResult ar)
        {
            var socket = ar.AsyncState as Socket;
            var clientSocket = socket.EndAccept(ar);
            Console.WriteLine($"{clientSocket.RemoteEndPoint}客户端连接");

            //客户端接收消息 如果客户端不发送数据 服务器程序阻塞(挂起)这个位置
            var buffer = new byte[1024];
            clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallBack, (clientSocket, buffer));
            int length = clientSocket.Receive(buffer);

            // 递归继续Accept
            socket.BeginAccept(AcceptCallBack, socket);
        }

        private static void ReceiveCallBack(IAsyncResult ar)
        {
            //这种是元组 匿名的结构体
            //这里的buffer数组只在新连接进来的时候,给每个新连接创建了一次,
            //后续与客户端通信的socket会绑定这个buffer数据,
            //通过复用这个buffer可以减少内存的申请和释放,提高性能。
            (var clientSocket, var buffer) = ((Socket, byte[]))ar.AsyncState;
            int length = clientSocket.EndReceive(ar);
            //小于0客户端就关闭了
            if (length>0)
            {
                Console.WriteLine($"接收到客户端的消息:{Encoding.UTF8.GetString(buffer, 0, length)}");
                clientSocket.Send(buffer, length, SocketFlags.None);
                //递归重新开始接收
                clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallBack, (clientSocket, buffer));
            }
            else
            {
                Console.WriteLine($"{clientSocket.RemoteEndPoint}断开连接");
                clientSocket.Close();
            }
        }
    }
}

相关文章

  • Unity网络编程(二)TCP 1V1聊天室

    服务端 先做个同步的 搭配不当就出异常常用组合 用VS窗口控制台 客户端 unity创建个项目 先运行服务器 再拖...

  • Python高级第三天

    网络编程初识 tcp聊天室 snd_tcp.py serv_tcp.py udp聊天室 snd_udp.py se...

  • 使用Socket实现TCP编程及聊天室的编写

    title: 『 Socket 』使用Socket实现TCP编程及聊天室的编写tags: socketcatego...

  • 谈谈Unity游戏TCP连接和网络重连

    谈谈Unity游戏TCP连接和网络重连 Unity中通常使用TcpClient来进行Tcp连接,TcpClient...

  • 二、Socket网络编程快速入门

    这是一个Socket网络编程的专题,将会讲解一些Socket相关的知识(TCP/UDP等),实现一个聊天室功能的项...

  • 安卓网络编程系列

    1.网络编程系列第(一)篇---TCP/IP 第一篇主要介绍TCP/IP协议组 2.网络编程系列第(二)篇---h...

  • 网络编程基础(二)

    网络编程基础(二) 四、简易聊天室的实现 在下面我们以一个简易的聊天室Demo进行socket的深入理解。 (一)...

  • 网络基础介绍

    网络编程的两种 TCP socket编程,是网络编程的主流。之所以叫Tcp socket编程,是因为底层是基于Tc...

  • 网络编程之TCP/IP协议

    网络编程之TCP/IP协议 网络编程分为两个不同的层次:一是基于Socket的低层次网络编程,二是基于URL的高层...

  • Python TCP编程

    Python网络编程之TCP 一、TCP协议 TCP协议,传输控制协议(Transmission Control ...

网友评论

      本文标题:Unity网络编程(二)TCP 1V1聊天室

      本文链接:https://www.haomeiwen.com/subject/wzacnctx.html