C# Udp协议 RakNet C-Sharp

RakNet

RakNet是一个基于UDP网络传输协议的C++网络库,允许程序员在他们自己的程序中实现高效的网络传输服务。通常情况下用于游戏.

 

个人编程环境 vs2017 /net4.5.1/C#

dll 引用

用到两个文件:RakNetDotNet.dll 和 RakNet.dll

RakNet库  https://github.com/OculusVR/RakNet

c#包装:https://github.com/RainsSoft/RakNet-C-Sharp-binding-project

c#包装项目名称: RakNet-C-Sharp-binding-project-master
    0.RakNet.dll 有两个 x86 和x64 版本 编译调试时要区分
    1.RakNetDotNet.dll 和 RakNet.dll 放到项目文件夹里
    2,Solution Explorer => 右键 References  => add References => Browse => RakNetDotNet.dll => ok button
  //  3.RakNet.dll 拖到 Solution Explorer 窗口的=>项目名字上
    4.调试或者编译运行时,先复制 RakNet.dll和RakNetDotNet.dll 文件 到 exe文件夹内

自己的封装

通过我的自己的封装一下.

Send方法中没有ip地址参数的,都是发给默认连接中的第一个

 connect 后,通过建立一个线程 后台执行 Rev ,不停解包 Packet

用包(Packet)的第一个字节(byte)表明包的类型(DefaultMessageIDTypes),而1个字节(byte)最多表示256种不同的状态
byte byte_ = Packet.data[0];
DefaultMessageIDTypes type =   (DefaultMessageIDTypes)byte_;

写入的时候       

BitStream bitStream = new BitStream();
bitStream.Write((byte)DefaultMessageIDTypes);
bitStream.Write(message);
Send(bitStream, PacketPriority.HIGH_PRIORITY, PacketReliability.RELIABLE_ORDERED, (char)0, SystemAddress地址, true);

读取

BitStream receiveBitStream;
receiveBitStream.Reset();
receiveBitStream.Write(date.p.data, date.p.length);
receiveBitStream.IgnoreBytes(1);
receiveBitStream.Read(out date.message); 

 

server

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using RakNet;
public class RakNetServe
{
    public RakNetClient_Date date;
    private RakNetServe() { }
    public RakNetServe(string serverPort)
    {
        date.serverPort = serverPort;
    }
    public void Init_Date()
    {
        date.ServeIp = "0"; //不需要
        date.Rumpelstiltskin = "Rumpelstiltskin"; //Password
        date.socketFamily = 2; // use IPv6 =  23,Ipv4 =2
        date.MAXIMUM_NUMBER_OF_INTERNAL_IDS = 10;
        date.rss = new RakNetStatistics();
        date.server = RakPeerInterface.GetInstance();
        date.server.SetIncomingPassword(date.Rumpelstiltskin, date.Rumpelstiltskin.Length);
        date.server.SetTimeoutTime(30000, RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS);
        date.server.SetMaximumIncomingConnections(4);
        //  System.Threading.Thread.Sleep(1000);
        date.server.SetOccasionalPing(true);
        date.server.SetUnreliableTimeout(1000);
        date.isServer = true;
        date.p = new Packet();
        date.receiveBitStream = new BitStream();
        date.clientID = RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS;
        date.isCONNECTION_ATTEMPT_STARTED = true;
        date.socketDescriptor = new SocketDescriptor(Convert.ToUInt16(date.serverPort), date.ServeIp);
        date.socketDescriptor.port = Convert.ToUInt16(date.serverPort);
        date.socketDescriptor.socketFamily = date.socketFamily;
        date.isInit = true;
    }
    public void Ban(string ip)
    {
        Console.WriteLine("'Enter IP to ban.  You can use * as a wildcard");
        date.server.AddToBanList(ip);
        Console.WriteLine("IP " + ip + " added to ban list.");
    }
    public void Kick()
    {
        date.server.CloseConnection(date.clientID, true, 0);
    }
    public List<SystemAddress> GetConnectionList()
    {
        SystemAddress[] systems = new SystemAddress[10];
        ushort numCons = 10;
        date.server.GetConnectionList(out systems, ref numCons);
        for (int i = 0; i < numCons; i++)
        {
            Console.WriteLine((i + 1).ToString() + ". " + systems[i].ToString(true));
        }
        return systems.ToList();
    }
    public void Close()
    {
        date.Rev_Thread?.Abort();
        date.server?.Shutdown(300);
        RakPeerInterface.DestroyInstance(date.server);
        date.isConnectFuncRuned = false;
        date.isInit = false;
        date.currDebugString = ("server close");
    }
    public void Send(string message)
    {
        date.server.Send(message, message.Length + 1, PacketPriority.HIGH_PRIORITY, PacketReliability.RELIABLE_ORDERED, (char)0, RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS, true);
        date.currDebugString = "\r\nTo:" + date.server.GetExternalID(RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS) + "|" + "\r\nSend:" + message + "\r\n" + date.currTime;
    }
    public void Send(BitStream bitStream)
    {
        date.message = Encoding.UTF8.GetString(bitStream.GetData().ToList().Skip(1).ToArray());
        date.server.Send(bitStream, PacketPriority.HIGH_PRIORITY, PacketReliability.RELIABLE_ORDERED, (char)0, RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS, true);
        date.currDebugString = "\r\nTo:" + date.server.GetExternalID(RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS) + "|" + "\r\nSend:" + date.message + "\r\n" + date.currTime;
    }
    public void Send(string message,SystemAddress systemAddress)
    {
        date.server.Send(message, message.Length + 1, PacketPriority.HIGH_PRIORITY, PacketReliability.RELIABLE_ORDERED, (char)0, date.server.GetExternalID(systemAddress), true);
        date.currDebugString = "\r\nTo:" + date.server.GetExternalID(systemAddress) + "\r\nSend:" + message + "\r\n" + date.currTime;
    }
    public void Send(string message, SystemAddress systemAddress, DefaultMessageIDTypes type)
    {
        BitStream bitStream = new BitStream();
        bitStream.Write((byte)type);
        bitStream.Write(message);
        date.server.Send(bitStream, PacketPriority.HIGH_PRIORITY, PacketReliability.RELIABLE_ORDERED, (char)0, date.server.GetExternalID(systemAddress), true);
        date.currDebugString = "\r\nTo:" + date.server.GetExternalID(systemAddress) + "\r\nSend:" + message + "\r\n" + date.currTime;
    }
    /// <summary>
    /// 发送指定类型的数据包
    /// </summary>
    /// <param name="message"></param>
    /// <param name="type"></param>
    public void Send(string message, DefaultMessageIDTypes type)
    {
        BitStream bitStream = new BitStream();
        bitStream.Write((byte)type);
        bitStream.Write(message);
        Send(bitStream);
    }
    /// <summary>
    /// 统计信息
    /// </summary>
    public string Stat()
    {
        date. rss = date.server.GetStatistics(date.server.GetSystemAddressFromIndex(0));
        RakNet.RakNet.StatisticsToString(date.rss, out date.message, 2);
        date.currDebugString = date.message;
        return date.message;
        /*
        Actual bytes per second sent         0
        Actual bytes per second received     0
        Message bytes per second sent        0
        Message bytes per second resent      0
        Message bytes per second pushed      0
        Message bytes per second returned    0
        Message bytes per second ignored     0
        Total bytes sent                     0
        Total bytes received                 0
        Total message bytes sent             0
        Total message bytes resent           0
        Total message bytes pushed           0
        Total message bytes returned         0
        Total message bytes ignored          0
        Messages in send buffer, by priority 0,0,0,0
        Bytes in send buffer, by priority    0,0,0,0
        Messages in resend buffer            0
        Bytes in resend buffer               0
        Current packetloss                   0.0 %
        Average packetloss                   0.0 %
        Elapsed connection time in seconds   24542
        */
    }
    public void Connect()
    {
        if (date.isInit == false)
        {
            Init_Date();
        }
        date.startupResult = date.server.Startup(4, date.socketDescriptor, 1);
        //maxConnections 游戏的最大玩家数
        //创建一个或多个sockets,这个使用socketDescriptors参数描述的变量
        if (date.startupResult != StartupResult.RAKNET_STARTED)
        {
            date.currDebugString = "Error starting server";
        }
        date.currDebugString = "server starting ...";
        date.currDebugString = "Listen ... Port: [" + date.serverPort + "]";
        for (int i = 0; i < date.server.GetNumberOfAddresses(); i++)
        {
            SystemAddress sa = date.server.GetInternalID(RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS, i);
            date.currDebugString = (i + 1).ToString() + ". " + sa.ToString() + "(LAN = " + sa.IsLANAddress() + ")";
        }
        date.currDebugString = ("My GUID is " + date.server.GetGuidFromSystemAddress(RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS).ToString());
        if (date.Rev_Thread != null)
        {
            date.Rev_Thread.Abort();
        }
        date.Rev_Thread = new Thread(Rev);
        date.Rev_Thread.Start();
        date.isConnected = true;
        date.isConnectFuncRuned = true;
    }
    void Rev()
    {
        while (true)
        {
            System.Threading.Thread.Sleep(30);
            for (date.p = date.server.Receive(); date.p != null; date.server.DeallocatePacket(date.p), date.p = date.server.Receive())
            {
                date.packetIdentifier = GetPacketIdentifier(date.p);
                date.currDefaultMessageIdTypes = (DefaultMessageIDTypes) date.packetIdentifier;
                switch (date.currDefaultMessageIdTypes)
                {
                    case DefaultMessageIDTypes.ID_DISCONNECTION_NOTIFICATION:
                        date.currDebugString = ("ID_DISCONNECTION_NOTIFICATION from " + date.p.systemAddress.ToString(true));
                        break;
                    case DefaultMessageIDTypes.ID_NEW_INCOMING_CONNECTION:
                        date.currDebugString = ("ID_NEW_INCOMING_CONNECTION from " + date.p.systemAddress.ToString(true) + "with GUID " + date.p.guid.ToString());
                        date.currDebugString = (System.Text.Encoding.UTF8.GetString(date.p.data));
                        date.clientID = date.p.systemAddress;
                        date.currDebugString = ("Remote internal IDs: ");
                        if (date.NewPlayerConnect != null) date.NewPlayerConnect(date.p.systemAddress);
                        for (int index = 0; index < date.MAXIMUM_NUMBER_OF_INTERNAL_IDS; index++)
                        {
                            SystemAddress internalId = date.server.GetInternalID(date.p.systemAddress, index);
                            if (internalId != RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS)
                            {
                                date.currDebugString = ((index + 1).ToString() + ". " + internalId.ToString(true));
                            }
                        }
                        break;
                    case DefaultMessageIDTypes.ID_INCOMPATIBLE_PROTOCOL_VERSION:
                        date.currDebugString = ("ID_INCOMPATIBLE_PROTOCOL_VERSION");
                        break;
                    case DefaultMessageIDTypes.ID_CONNECTED_PING:
                    case DefaultMessageIDTypes.ID_UNCONNECTED_PING:
                        date.currDebugString = ("Ping from " + date.p.systemAddress.ToString(true));
                        break;
                    case DefaultMessageIDTypes.ID_CONNECTION_LOST:
                        date.currDebugString = ("ID_CONNECTION_LOST from " + date.p.systemAddress.ToString(true));
                        if (date.PlayerConnectLost != null) date.PlayerConnectLost(date.p.systemAddress);
                        break;
                    case DefaultMessageIDTypes.ID_USER_PACKET_ENUM:
                        date.receiveBitStream.Reset();
                        date.receiveBitStream.Write(date.p.data, date.p.length);
                        date.receiveBitStream.IgnoreBytes(1);
                        date.receiveBitStream.Read(out date.message);
                        date.currDebugString = "\r\nBy " + date.p.systemAddress.ToString() +
                                               " Rev msg \r\nDefaultMessageIdTypes: " +
                                               Enum.GetName(typeof(DefaultMessageIDTypes), date.currDefaultMessageIdTypes) +
                                               "\r\n" + date.currTime +
                                               "\r\n" + date.currTime +
                                               "\r\nMsg:" + date.message;
                        break;
                    default:
                        date.message = Encoding.UTF8.GetString(date.p.data);
                        if (date.Rev_Msg != null) date.Rev_Msg(date.message);
                        date.currDebugString = "\r\nBy " + date.p.systemAddress.ToString() +
                                               " Rev msg \r\nDefaultMessageIdTypes: " +
                                               Enum.GetName(typeof(DefaultMessageIDTypes), date.currDefaultMessageIdTypes) +
                                               "\r\n" + date.currTime +
                                               "\r\nMsg:" + date.message;
                        Send("i Rev Msg:[" +date.message+"]");
                        break;
                }
            }
        }
    }
    private static byte GetPacketIdentifier(Packet p)
    {
        if (p == null)
            return 255;
        byte buf = p.data[0];
        if (buf == (char)DefaultMessageIDTypes.ID_TIMESTAMP)
        {
            return (byte)p.data[5];
        }
        else
            return buf;
    }
}

client 

using System;
using System.Linq;
using System.Text;
using System.Threading;
using RakNet;
public class RakNetClient
{
    public RakNetClient_Date date;
    private static bool _isActive;
    public bool isActive
    {
        get
        {
            if (date.client == null)
                return false;
            if (date.isInit && date.isConnectFuncRuned && date.isConnected)
            {
                _isActive = date.client.IsActive();//C++ dll  需要静态变量来接受
                return _isActive;
            }
            return false;
        }
    }
    public RakNetClient(string ServeIp, string serverPort)
    {
        date.ServeIp = ServeIp;
        date.serverPort = serverPort;
    }
    public void Init_Date()
    {
        //作为客户端时,就使用0表示使用系统自动分配
        date.clientIp = "0";
        date.clientPort = "0";
        date.isServer = false;
        date.socketFamily = 2;  // use IPv6 =23,Ipv4 =2
        date.Rumpelstiltskin = "Rumpelstiltskin"; //Password
        date.client = RakPeerInterface.GetInstance();
        date.rss = new RakNetStatistics();
        date.clientID = RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS;
        date.isCONNECTION_ATTEMPT_STARTED = true;
        date.socketDescriptor = new SocketDescriptor(Convert.ToUInt16(date.clientPort), date.clientIp);
        date.socketDescriptor.socketFamily = date.socketFamily;
        date.client.Startup(8, date.socketDescriptor, 1);
        date.client.SetOccasionalPing(true);
        date.receiveBitStream = new BitStream();
        date.p = new Packet();
        date.isInit = true;
    }
    void ConnectFail()
    {
        date.isConnected = false;
        if (date.Connect_Fail != null)
            date.Connect_Fail();
    }
    void Rev()
    {
        while (true)
        {
            Thread.Sleep(30);
            for (date.p = date.client.Receive(); date.p != null; date.client.DeallocatePacket(date.p), date.p = date.client.Receive())
            {
                date.packetIdentifier = GetPacketIdentifier(date.p);
                date.currDefaultMessageIdTypes = (DefaultMessageIDTypes)date.packetIdentifier;
                switch (date.currDefaultMessageIdTypes)
                {
                    case DefaultMessageIDTypes.ID_DISCONNECTION_NOTIFICATION:
                        date.currDebugString = ("ID_DISCONNECTION_NOTIFICATION");
                        ConnectFail();
                        break;
                    case DefaultMessageIDTypes.ID_ALREADY_CONNECTED:
                        date.currDebugString = ("ID_ALREADY_CONNECTED with guid " + date.p.guid);
                        break;
                    case DefaultMessageIDTypes.ID_INCOMPATIBLE_PROTOCOL_VERSION:
                        date.currDebugString = ("ID_INCOMPATIBLE_PROTOCOL_VERSION ");
                        break;
                    case DefaultMessageIDTypes.ID_REMOTE_DISCONNECTION_NOTIFICATION:
                        date.currDebugString = ("ID_REMOTE_DISCONNECTION_NOTIFICATION ");
                        break;
                    case DefaultMessageIDTypes.ID_REMOTE_CONNECTION_LOST: // Server telling the date.clients of another date.client disconnecting forcefully.  You can manually broadcast this in a peer to peer enviroment if you want.
                        date.currDebugString = ("ID_REMOTE_CONNECTION_LOST");
                        ConnectFail();
                        break;
                    case DefaultMessageIDTypes.ID_CONNECTION_BANNED: // Banned from this server
                        date.currDebugString = ("We are banned from this server.\n");
                        break;
                    case DefaultMessageIDTypes.ID_CONNECTION_ATTEMPT_FAILED:
                        date.currDebugString = ("Connection attempt failed ");
                        ConnectFail();
                        break;
                    case DefaultMessageIDTypes.ID_NO_FREE_INCOMING_CONNECTIONS:
                        date.currDebugString = ("Server is full ");
                        break;
                    case DefaultMessageIDTypes.ID_INVALID_PASSWORD:
                        date.currDebugString = ("ID_INVALID_PASSWORD\n");
                        break;
                    case DefaultMessageIDTypes.ID_CONNECTION_LOST:
                        ConnectFail();
                        // Couldn't deliver a reliable packet - i.e. the other system was abnormally
                        // terminated
                        date.currDebugString = ("ID_CONNECTION_LOST\n");
                        break;
                    case DefaultMessageIDTypes.ID_CONNECTION_REQUEST_ACCEPTED:
                        if (date.Connect_Success != null) date.Connect_Success();
                        // This tells the date.client they have connected
                        date.currDebugString = ("ID_CONNECTION_REQUEST_ACCEPTED to %s " + date.p.systemAddress.ToString() + "with GUID " + date.p.guid.ToString());
                        date.currDebugString = ("My external address is:" + date.client.GetExternalID(date.p.systemAddress).ToString());
                        break;
                    case DefaultMessageIDTypes.ID_CONNECTED_PING:
                    case DefaultMessageIDTypes.ID_UNCONNECTED_PING:
                        date.currDebugString = ("Ping from " + date.p.systemAddress.ToString(true));
                        break;
                    case DefaultMessageIDTypes.ID_USER_PACKET_ENUM:
                        date.receiveBitStream.Reset();
                        date.receiveBitStream.Write(date.p.data, date.p.length);
                        date.receiveBitStream.IgnoreBytes(1);
                        date.receiveBitStream.Read(out date.message);
                        date.currDebugString = "\r\nBy " + date.p.systemAddress.ToString() +
                                               " Rev msg \r\nDefaultMessageIdTypes: " +
                                               Enum.GetName(typeof(DefaultMessageIDTypes), date.currDefaultMessageIdTypes) +
                                               "\r\n" + date.currTime +
                                               "\r\n" + date.currTime +
                                               "\r\nMsg:" + date.message;
                        break;
                    default:
                        date.message = Encoding.UTF8.GetString(date.p.data.Skip(0).ToArray());
                        date.currDebugString = "\r\nBy " + date.p.systemAddress.ToString() +
                                               " Rev msg \r\nDefaultMessageIdTypes: " +
                                               Enum.GetName(typeof(DefaultMessageIDTypes), date.currDefaultMessageIdTypes) +
                                               "\r\n" + date.currTime +
                                               "\r\nMsg:" + date.message;
                        if (date.Rev_Msg != null) date.Rev_Msg(date.message);
                        break;
                }
            }
        }
    }
    /*
    public virtual uint Send(
      string data,
      int length,
      PacketPriority priority,
      PacketReliability reliability,
      char orderingChannel,
      AddressOrGUID systemIdentifier,
      bool broadcast,
      uint forceReceiptNumber)
    {
      uint num = RakNetPINVOKE.RakPeerInterface_Send__SWIG_0(this.swigCPtr, data, length, (int) priority, (int) reliability, orderingChannel, AddressOrGUID.getCPtr(systemIdentifier), broadcast, forceReceiptNumber);
      if (RakNetPINVOKE.SWIGPendingException.Pending)
        throw RakNetPINVOKE.SWIGPendingException.Retrieve();
      return num;
    }
    public virtual uint Send(
      string data,
      int length,
      PacketPriority priority,
      PacketReliability reliability,
      char orderingChannel,
      AddressOrGUID systemIdentifier,
      bool broadcast)
    {
      uint num = RakNetPINVOKE.RakPeerInterface_Send__SWIG_1(this.swigCPtr, data, length, (int) priority, (int) reliability, orderingChannel, AddressOrGUID.getCPtr(systemIdentifier), broadcast);
      if (RakNetPINVOKE.SWIGPendingException.Pending)
        throw RakNetPINVOKE.SWIGPendingException.Retrieve();
      return num;
    }
     */
    public void Send(string message)
    {
        if (date.client != null && isActive)
        {
            if (message.Length > 0)
            {
                date.client.Send(message, message.Length + 1, PacketPriority.HIGH_PRIORITY, PacketReliability.RELIABLE_ORDERED, (char)0, RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS, true);
                // PacketPriority.HIGH_PRIORITY 每一种优先级的发送次数大约是比它优先级低的快两倍。例如,如果HIGH_PRIORITY发送2条消息,在大致相同的时间内只会发送一条IMMEDIATE_PRIORITY消息。奇怪的是IMMEDIATE_PRIORITY可能会首先到达目的端。
                //PacketReliability.RELIABLE_ORDERED 用RELIABLE_ORDERED作为数据包的可靠性类型。对于所有的有序类型,使用有序流,下面会介绍到。
                date.currDebugString = "\r\nTo:" + date.client.GetExternalID(RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS).ToString() + "\r\n" + date.currTime + "\r\nSend:" + message;
            }
            else
            {
                date.currDebugString = ("Send message fail : you message Length <= 0");
            }
        }
        else
        {
            date.currDebugString = ("because client.IsActive equal false ,So Send message fail :" + message);
        }
    }
    public void Send(BitStream bitStream)
    {
        date.message = Encoding.UTF8.GetString(bitStream.GetData().ToList().Skip(1).ToArray());
        if (date.client != null && isActive)
        {
            // PacketPriority.HIGH_PRIORITY 每一种优先级的发送次数大约是比它优先级低的快两倍。例如,如果HIGH_PRIORITY发送2条消息,在大致相同的时间内只会发送一条IMMEDIATE_PRIORITY消息。奇怪的是IMMEDIATE_PRIORITY可能会首先到达目的端。
            //PacketReliability.RELIABLE_ORDERED 用RELIABLE_ORDERED作为数据包的可靠性类型。对于所有的有序类型,使用有序流,下面会介绍到。
            date.client.Send(bitStream, PacketPriority.HIGH_PRIORITY, PacketReliability.RELIABLE_ORDERED, (char)0, RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS, true);
            date.currDebugString = "\r\nTo:" + date.client.GetExternalID(RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS).ToString() + "\r\n" + date.currTime + "\r\nSend:" + bitStream.ToString();
        }
        else
        {
            date.currDebugString = ("because client.IsActive equal false ,So Send message fail :" + date.message);
        }
    }
    /// <summary>
    /// 发送指定类型的数据包
    /// </summary>
    /// <param name="message"></param>
    /// <param name="type"></param>
    public void Send(string message, DefaultMessageIDTypes type)
    {
        BitStream bitStream = new BitStream();
        bitStream.Write((byte)type);
        bitStream.Write(message);
        Send(bitStream);
    }
    //SystemAddress 的知识
    AddressOrGUID SystemAddressToAddressOrGUID(string ip, ushort port)
    {
        //内网用户 从包中获取 自己公网ip ,GetExternalID 获取公网ip 
        date.client.GetExternalID(date.p.systemAddress).ToString();  //   " 120.77.0.244 | 63279" 
        //默认连接中第一个地址
        //RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS
        //本地地址
        //SystemAddress.Tostring();
        //构建
        var SystemAddress_ = new SystemAddress(ip, port);
        var s = new AddressOrGUID(new SystemAddress(ip, port));
        return s;
    }
    public void Close()
    {
        if (date.isInit && date.isConnectFuncRuned)
        {
            date.Rev_Thread?.Abort();
            date.client?.Shutdown(300); //停工;关闭
            RakPeerInterface.DestroyInstance(date.client);
            date.isConnectFuncRuned = false;
            date.isInit = false;
            date.currDebugString = ("connected close  [" + date.ServeIp + ":" + date.serverPort + "] " + "\r\n" + date.currTime);
        }
    }
    /// <summary>
    /// Init 后,可以更换 新的服务器的 ip 端口
    /// </summary>
    public void Connect(string newIp, string newPort)
    {
        if (date.client != null)
        {
            Close();
        }
        date.ServeIp = newIp;
        date.serverPort = newPort;
        Connect();
    }
    public void Connect()
    {
        if (date.isInit == false)
        {
            Init_Date();
        }
        date.currDebugString = "Connecting ... [" + date.ServeIp + ":" + date.serverPort + "]";
        if (date.isCONNECTION_ATTEMPT_STARTED)
        {
            date.car = date.client.Connect(date.ServeIp, Convert.ToUInt16(date.serverPort), date.Rumpelstiltskin, date.Rumpelstiltskin.Length);
            /*
 1. host是一个IP地址,或域名
       2. remotePort是远端系统监听的端口,传递给Startup()函数的端口参数。
       3. passwordData是随着连接请求发送的二进制数据。如果这个参数与传递给RakPeerInterface::SetPassword()的参数不同,远端系统会回复ID_INVALID_PASSWORD。
       4. passwordDataLength是passwordData的长度,单位是字节。
       5. publicKey 是远端系统上传递给InitializeSecurity()函数的公用密钥参数。如果你不适用,传递0。
       6. connectionSocketINdex是你要发送的客户端的Socket在传递给RakPeer::Startup()函数的socket描述符的数组中的索引。
       7. sendConnectionAttemptCount是在确定无法连接前要做出的发送尝试次数。这个也用于MTU检测,使用3个不同的MTU大小。默认的值12意味着发送每个MTU四次,这对于容忍任何原因的包丢失也是足够的了。更低的值意味着ID_CONNECTION_ATTEMPT_FAILED会更快返回。
       8. timeBetweenSendConnectionAttemptsMS是进行另外一次连接尝试要等待的毫秒数。比较好的值是4倍的ping值。
       9. 如果消息不能发送,在丢掉远端系统之前,为这次连接,timeoutTime指出了要等待多少毫秒。默认值是0,意味着使用SetTimeoutTime()方法中的全局值。
   连接尝试成功Connect()会返回CONNECTION_ATTEMPT_STARTED值,如果失败会返回其他的值。
   注意:Connect()返回TRUE并不意味着已经连接成功。如果连接成功,应该会返回ID_CONNECTION_REQUEST_ACCEPTED。否则,会收到一条错误消息。
连接消息作为Packet::data结构的第一个字节返回
             */
            if (date.car != RakNet.ConnectionAttemptResult.CONNECTION_ATTEMPT_STARTED)
                throw new Exception();
            date.isCONNECTION_ATTEMPT_STARTED = false;
        }
        else
        {
            ConnectionAttemptResult car2 = date.client.Connect(date.ServeIp, Convert.ToUInt16(date.serverPort), date.Rumpelstiltskin, date.Rumpelstiltskin.Length);
        }
        date.currDebugString = "My Local IP Addresses:";
        for (uint i = 0; i < date.client.GetNumberOfAddresses(); i++)
        {
            date.currDebugString = date.client.GetLocalIP(i).ToString();
        }
        date.currDebugString = "My GUID is " + date.client.GetGuidFromSystemAddress(RakNet.RakNet.UNASSIGNED_SYSTEM_ADDRESS).ToString();
        if (date.Rev_Thread != null)
        {
            date.Rev_Thread.Abort();
        }
        date.Rev_Thread = new Thread(Rev);
        date.Rev_Thread.Start();
        date.isConnected = true;
        date.isConnectFuncRuned = true;
    }
    public void Disconnect(string index_str)
    {
        uint index = Convert.ToUInt32(index_str, 16);
        date.client.CloseConnection(date.client.GetSystemAddressFromIndex(index), false);
        date.currDebugString = "Disconnecting index :" + index_str;
    }
    /*
用包(Packet)的第一个字节(byte)表明包的类型(DefaultMessageIDTypes),而1个字节(byte)最多表示256种不同的状态
byte byte_ = Packet.data[0];
DefaultMessageIDTypes type =   (DefaultMessageIDTypes)byte_;
     */
    /// <summary>
    /// 确定数据包类型
    /// </summary>
    /// <param name="p"></param>
    /// <returns></returns>
    private static byte GetPacketIdentifier(Packet p)
    {
        if (p == null)
            return 255;
        byte buf = p.data[0];
        if (buf == (char)DefaultMessageIDTypes.ID_TIMESTAMP)
        {
            return (byte)p.data[5];
        }
        else
            return buf;
    }
}
public struct RakNetClient_Date
{
    public RakPeerInterface client;
    public SystemAddress clientID;
    public RakNetStatistics rss;
    public SocketDescriptor socketDescriptor;
    public string ServeIp, serverPort, clientPort, clientIp;
    public ConnectionAttemptResult car;
    public bool isServer;
    public string Rumpelstiltskin;
    public Packet p;
    public byte packetIdentifier;
    public bool isCONNECTION_ATTEMPT_STARTED;//是否是第一次连接
    public bool isInit;//是否初始化了Date
    public bool isConnectFuncRuned;// Connect函数是否执行过
    public bool isConnected;
    public Thread Rev_Thread;
    public Action<string> Rev_Msg; //收到数据 事件 消息回调
    public Action<string> Debug_Msg; //调试信息 事件 消息回调
    public BitStream receiveBitStream;
    public string currDebugString
    {
        set
        {
            if (Debug_Msg != null)
                Debug_Msg(value);
        }
    }
    public DefaultMessageIDTypes currDefaultMessageIdTypes;
    public Action Connect_Fail; //连接失败 或者 失去连接 事件 消息回调
    public Action Connect_Success; //连接成功事件 消息回调
    public StartupResult startupResult;
    public short socketFamily;
    public string message;
    //Serve
    public RakPeerInterface server;
    public int MAXIMUM_NUMBER_OF_INTERNAL_IDS;
    public Action<SystemAddress> NewPlayerConnect; //新玩家接入时
    public Action<SystemAddress> PlayerConnectLost; //失去玩家连接时
    public string currTime
    {
        get
        {
            return "Time:" + System.DateTime.Now.ToString("yyyy_MM_dd hh:mm:ss:fff");
        }
    }
}

Use

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using RakNet;
namespace RakNetDot
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            var textBox8897 = textBox3;
            //多行
            textBox8897.Multiline = true;
            //不自动换行
            textBox8897.WordWrap = true;
            //添加滚动条,,  ScrollBars.Horizontal=横,ScrollBars.Vertical=竖,
            textBox8897.ScrollBars = ScrollBars.Vertical;
            //textbox滚动条保持在最下面
            textBox8897.TextChanged += (sender, args) =>
            {
                textBox8897.SelectionStart = textBox8897.Text.Length;
                textBox8897.SelectionLength = 0;
                textBox8897.ScrollToCaret();
            };
             textBox8897 = textBox6;
            //多行
            textBox8897.Multiline = true;
            //不自动换行
            textBox8897.WordWrap = true;
            //添加滚动条,,  ScrollBars.Horizontal=横,ScrollBars.Vertical=竖,
            textBox8897.ScrollBars = ScrollBars.Vertical;
            //textbox滚动条保持在最下面
            textBox8897.TextChanged += (sender, args) =>
            {
                textBox8897.SelectionStart = textBox8897.Text.Length;
                textBox8897.SelectionLength = 0;
                textBox8897.ScrollToCaret();
            };
        }
        private RakNetClient client;
        private RakNetServe rakNetServe;
        private void button1_Click(object sender, EventArgs e)
        {//连接
            if (client == null || client.date.client == null) //新建
            {
                string Serve_ip = textBox1.Text;
                string Serve_port = textBox2.Text;
                client = new RakNetClient(Serve_ip, Serve_port);
                client.date.Debug_Msg += x =>
                {
                    // 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它
                    if (textBox3.InvokeRequired)
                    {
                        Action<string> actionDelegate = (txt) => { textBox3.AppendText("\r\n" + txt + "\r\n"); };
                        textBox3.Invoke(actionDelegate, x);
                    }
                    else
                    {
                        textBox3.AppendText("\r\n" + x + "\r\n");
                    }
                };
                client.date.Debug_Msg += x => { Console.WriteLine(x); };
                client.Connect(Serve_ip, Serve_port);
                client.date.Connect_Fail += () =>
                {
                    // 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它
                    if (button1.InvokeRequired)
                    {
                        Action<string> actionDelegate = (txt) => { button1.Text = (txt); };
                        button1.Invoke(actionDelegate, "connect");
                    }
                    else
                    {
                        button1.Text = "connect";
                    }
                };
            }
            else if (client.date.isInit==false || client.isActive == false) //重连
            {
                client.Connect();
            }
            else if (client.date.isInit && client.isActive) //关闭
            {
                client.Close();
            }
            if (client != null)
            {
                button1.Text = client.isActive ? "Stop connect" : "connect";
            }
            else
            {
                button1.Text = "connect";
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {//发送
            client?.Send(textBox4.Text,DefaultMessageIDTypes.ID_USER_PACKET_ENUM);
        }
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            client?.Close();
            rakNetServe?.Close();
        }
        List<SystemAddress> list =new List<SystemAddress>();
        private void button4_Click(object sender, EventArgs e)
        {
            if (rakNetServe == null)
            {
                string Serve_port = textBox7.Text;
                rakNetServe = new RakNetServe(Serve_port);
                rakNetServe.date.Debug_Msg += x =>
                {
                    // 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它
                    if (textBox6.InvokeRequired)
                    {
                        Action<string> actionDelegate = (txt) => { textBox6.AppendText("\r\n" + txt + "\r\n"); };
                        textBox6.Invoke(actionDelegate, x);
                    }
                    else
                    {
                        textBox6.AppendText("\r\n" + x + "\r\n");
                    }
                };
                rakNetServe.date.NewPlayerConnect += x =>
                {
                    list.Clear();
                    list = rakNetServe.GetConnectionList();
                    if (list.Count > 0)
                    {
                        var kvDictonary = new Dictionary<string, string>();
                        for (int i = 0; i < list.Count; i++)
                        {
                            var item = list[i];
                            kvDictonary.Add(item.ToString(), item.ToString());
                        }
                        BindingSource bs = new BindingSource();
                        bs.DataSource = kvDictonary;
                        comboBox1.DataSource = bs;
                        comboBox1.ValueMember = "Key";
                        comboBox1.DisplayMember = "Value";
                    }
                };
                rakNetServe.date.PlayerConnectLost += x =>
                {
                    list.Clear();
                    list = rakNetServe.GetConnectionList();
                    if (list.Count > 0)
                    {
                        var kvDictonary = new Dictionary<string, string>();
                        for (int i = 0; i < list.Count; i++)
                        {
                            var item = list[i];
                            kvDictonary.Add(item.ToString(), item.ToString());
                        }
                        BindingSource bs = new BindingSource();
                        bs.DataSource = kvDictonary;
                        comboBox1.DataSource = bs;
                        comboBox1.ValueMember = "Key";
                        comboBox1.DisplayMember = "Value";
                    }
                };
                rakNetServe.Connect();
                button4.Text = "Stop";
            }
            else
            {
                rakNetServe.Close();
                button4.Text = "Listen";
            }
        }
        private void button3_Click(object sender, EventArgs e)
        {
            if (list.Count > 0 && comboBox1.SelectedIndex >=0 && comboBox1.SelectedIndex < list.Count)
            {
                SystemAddress add = list[comboBox1.SelectedIndex];
                rakNetServe.Send(textBox5.Text,add,DefaultMessageIDTypes.ID_USER_PACKET_ENUM);
            }
            else
            {
                textBox6.AppendText("\r\n" + "send msg fail ,becucase no player" + "\r\n");
            }
        }
    }
}

exe 程序在 qq群文件夹里 431859012

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值