public void Connect(string host, int port) { if (m_Dispose) { throw new ObjectDisposedException("ClientSocket already dispose!"); } if (IsConnected) { Logger.Error($"已连接 {host}:{port}"); return; } if (m_Status == Status.Connecting) { Logger.Error($"正在连接中 {host}:{port}"); return; } m_Status = Status.Connecting; IPAddress[] addresses = Dns.GetHostAddresses(host); if (addresses.Length < 1) { throw new ArgumentException($"不能解析的地址:{host}"); } IPEndPoint point = new IPEndPoint(addresses[0], port); m_Socket = new Socket(point.AddressFamily, SocketType.Dgram, ProtocolType.Udp); KcpHelper.CreateThread(OnConnectLooper, point); }
public void Output(Memory <byte> memory, int length) { if (m_Dispose) { return; } KcpHelper.Encode32u(m_OutputBuffer, 0, m_ConId); m_OutputBuffer[KcpConstants.Conv_Size] = MsgChannel.Reliable; memory.Span.Slice(0, length).CopyTo(new Span <byte>(m_OutputBuffer, KcpConstants.Head_Size, length)); OnSendData(m_OutputBuffer, 0, length + KcpConstants.Head_Size); }
public void Bind(int port, IChannelListener listener) { if (m_Dispose) { throw new ObjectDisposedException("ServerTransport already disposed!"); } m_Listener = listener; m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); m_Socket.Bind(new IPEndPoint(IPAddress.Any, port)); KcpHelper.CreateThread(RecvUdpDataLooper); KcpHelper.CreateThread(UpdateChannelLooper); }
public int RawSend(byte[] buffer, int offset, int length) { if (m_Dispose) { return(-10); } KcpHelper.Encode32u(m_OutputBuffer, 0, m_ConId); m_OutputBuffer[KcpConstants.Conv_Size] = MsgChannel.Unreliable; Array.Copy(buffer, offset, m_OutputBuffer, KcpConstants.Head_Size, length); OnSendData(m_OutputBuffer, 0, length + KcpConstants.Conv_Size + 1); return(length + KcpConstants.Head_Size); }
private void RecvUdpDataLooper(object obj) { try { uint startConvId = 10000; const int pollTimeout = 100000; List <Packet> packets = new List <Packet>(); byte[] rawBuffer = new byte[KcpConstants.Packet_Length]; EndPoint remote = new IPEndPoint(IPAddress.Any, 0); while (!m_Dispose) { if (!m_Socket.Poll(pollTimeout, SelectMode.SelectRead)) { continue; } if (m_Dispose) { break; } int size = m_Socket.ReceiveFrom(rawBuffer, SocketFlags.None, ref remote); if (size > 0) { uint cid = (uint)remote.GetHashCode(); if (!m_Channels.TryGetValue(cid, out ServerChannel channel)) { if (size == 4) { uint flag = KcpHelper.Decode32u(rawBuffer, 0); if (flag == KcpConstants.Flag_Connect) { uint conv = startConvId++; EndPoint point = remote.Create(remote.Serialize()); channel = new ServerChannel(new KcpConServer(cid, conv, m_Socket, point)); if (m_Channels.TryAdd(cid, channel)) { KcpHelper.Encode32u(rawBuffer, 0, KcpConstants.Flag_Connect); KcpHelper.Encode32u(rawBuffer, 4, conv); channel.Send(rawBuffer, 0, 8); channel.Flush(); } } } else { Logger.Error($"not connect size={size}"); } } else if (size > KcpConstants.Head_Size) { uint remoteCid = KcpHelper.Decode32u(rawBuffer, 0); if (cid == remoteCid) { byte msgChannel = rawBuffer[KcpConstants.Conv_Size]; if (msgChannel == MsgChannel.Reliable) { channel.Input(rawBuffer, KcpConstants.Head_Size, size - KcpConstants.Head_Size); channel.RecvReliablePackets(m_Process, packets, m_Listener); } else if (msgChannel == MsgChannel.Unreliable) { channel.RecvUnreliablePackets(rawBuffer, KcpConstants.Head_Size, size - KcpConstants.Head_Size, m_Process, packets); } } else { Logger.Error($"conv {cid} != {remoteCid}"); } } else { Logger.Error($"size={size} < {KcpConstants.Head_Size}"); } } } } catch (Exception e) { Logger.Error(e.ToString()); } }
private void OnHandleLooper(object obj) { try { List <Packet> packets = new List <Packet>(); byte[] rawBuffer = new byte[KcpConstants.Packet_Length]; ClientDataProcessing process = new ClientDataProcessing(); ClientHeartbeatProcessing heartbeat = new ClientHeartbeatProcessing(); while (!m_Dispose && m_Status == Status.Success) { if (m_SendPackets.Count > 0) { process.SendPackets(m_Kcp, m_SendPackets); } long time = TimeUtils.Get1970ToNowMilliseconds(); m_Kcp.OnUpdate(time); heartbeat.UpdateHeartbeat(this, m_Kcp, time); while (m_Socket.Poll(0, SelectMode.SelectRead)) { int count = m_Socket.Receive(rawBuffer, 0, rawBuffer.Length, SocketFlags.None); if (count > KcpConstants.Head_Size) { uint remoteCid = KcpHelper.Decode32u(rawBuffer, 0); if (remoteCid == m_Kcp.ConId) { byte msgChannel = rawBuffer[KcpConstants.Conv_Size]; if (msgChannel == MsgChannel.Reliable) { m_Kcp.Input(rawBuffer, KcpConstants.Head_Size, count - KcpConstants.Head_Size); process.RecvReliablePackets(this, m_Kcp, packets, heartbeat); } else if (msgChannel == MsgChannel.Unreliable) { process.RecvUnreliablePackets(rawBuffer, KcpConstants.Head_Size, count - KcpConstants.Head_Size, packets); } int length = packets.Count; if (length > 0) { for (int i = 0; i < length; ++i) { m_RecvPackets.Enqueue(packets[i]); } packets.Clear(); } } } } Thread.Sleep(5); } } catch (Exception e) { Logger.Error(e.ToString()); if (m_Status == Status.Success) { m_Status = Status.Disconnect; } } finally { if (!m_Dispose) { if (m_Status == Status.Disconnect) { m_Register.Notify(Msg.Disconnect); } } } }
private void OnConnectLooper(object point) { try { int time = 0; const int tick = 100; const int timeout = 5000; const int pollTimeout = 100000; byte[] rawBuffer = new byte[KcpConstants.Packet_Length]; m_Socket.Connect((EndPoint)point); while (!m_Dispose && m_Status == Status.Connecting) { int size = KcpHelper.Encode32u(rawBuffer, 0, KcpConstants.Flag_Connect); m_Socket.Send(rawBuffer, 0, size, SocketFlags.None); if (!m_Socket.Poll(pollTimeout, SelectMode.SelectRead)) { time += tick; if (time >= timeout) { m_Status = Status.Timeout; break; } continue; } if (m_Dispose) { break; } int count = m_Socket.Receive(rawBuffer, 0, rawBuffer.Length, SocketFlags.None); if (count == 37) { uint cid = KcpHelper.Decode32u(rawBuffer, 0); uint flag = KcpHelper.Decode32u(rawBuffer, 29); uint conv = KcpHelper.Decode32u(rawBuffer, 33); if (flag == KcpConstants.Flag_Connect) { m_Kcp = new KcpConClient(cid, conv, m_Socket); m_Kcp.Input(rawBuffer, KcpConstants.Head_Size, count - KcpConstants.Head_Size); count = m_Kcp.Recv(rawBuffer, 0, rawBuffer.Length); if (count == 8) { KcpHelper.Encode32u(rawBuffer, 0, KcpConstants.Flag_Connect); KcpHelper.Encode32u(rawBuffer, 4, conv); m_Kcp.Send(rawBuffer, 0, 8); m_Kcp.Flush(); m_ConId = cid; m_Status = Status.Success; m_Register.Notify(Msg.Success); KcpHelper.CreateThread(OnHandleLooper); break; } } } } } catch (Exception e) { Logger.Error(e.ToString()); m_Status = Status.Error; } finally { if (!m_Dispose) { if (m_Status == Status.Error) { m_Register.Notify(Msg.Error); } else if (m_Status == Status.Timeout) { m_Register.Notify(Msg.Timeout); } } } }