public NetPackage(int headerSize, int bufferSize) { size = headerSize; //! size of all data contain header and user data _headerSize = headerSize; //! size of all data contain header and user data data = new byte[bufferSize]; //! it also contains header header = new NetHeader(); //! no allocation needed. It just points to data }
/// <summary> Detects acknowledged and lost messages. </summary> private void AckDelivered(NetHeader header) { for (int i = 0; i < sendWindow.Count; i++) { int seqDist = NetMath.SeqDistance(sendWindow[i], header.AckSequence); // This AckSequence is older than the sendWindow's, not useful: if (seqDist > 0) { break; } // AckHistory has rolled over without acking this message; Ordered reliable is broken: if (seqDist <= -64) { Connection.Disconnect(); } // If the seqDistance corresponds to a true bit in the AckHistory, message delivered/acked: else if (IsAcked(header.AckHistory, seqDist)) { MessageDelivered(i, header); i--; // Since the sendWindow count will decrease, the index needs to be adjusted. } // The seqDist is still within the send window, but if too much time has passed, assume lost: else if (NetTime.Milliseconds() - sendWindowTime[i] > 333) { MessageLost(i); } } }
/// <summary> Adds an out-of-order datagram to the buffer to await future delivery. </summary> private void BufferOutOfOrder(int seqDist, NetStream strm, NetHeader header) { if (recvBuffer.Count >= 512) { Connection.Disconnect(); return; } if (recvBufferSeqDist.Contains(seqDist)) { strm.Release(); return; } // Ack history window is only 64 bits, so only ack if within window: if (seqDist < 64) { AckReceived(header); AckDelivered(header); } else { strm.Pos = 1; // Reset to 1 so header can be reprocessed when seqDist < 64 } recvBuffer.Add(strm); recvBufferSeqDist.Add(seqDist); }
/// <summary> Handles a stream based on its header/size. Determines if it should be buffered if out-of-order, /// acked and released if size is equal to header size (ack only), or delivered immediately. </summary> internal void RouteIncomingStream(NetStream strm) { var header = NetHeader.FromStream(strm); int seqDist = NetMath.SeqDistance(header.ObjSequence, LastAcceptedRemoteSequence); // If the stream is only the size of a header, it's likely a forced ack: if (strm.Length <= 120) { AckDelivered(header); strm.Release(); } else if (!RemoteSequenceValid(seqDist)) { strm.Release(); } else if (seqDist != 1) { BufferOutOfOrder(seqDist, strm, header); } else { AckReceived(header); AckDelivered(header); DeliverStream(strm); } }
public bool VerifyPackage(byte[] buffer, int size, ulong lastNumber) { // validate message size if (size < NET_HEADER_SIZE || size > NET_BUFF_SIZE) { return(false); } NetHeader nh = ByteArrayToNetHeader(buffer); // validate net id if (nh.netId != NET_ID) { return(false); } // validate if message is duplicated //if ( nh.number == lastNumber && set_hasnt( nh.option, NET_OPTN_SAFESEND ) ) // return false; // validate data checksum if (size > NET_HEADER_SIZE) { if (nh.checksum != ComputeChecksum(buffer)) { return(false); } } // new we can suppose that the package is valid return(true); }
public byte[] NetHeaderToByteArray(NetHeader header) { byte[] buffer = new byte[NET_HEADER_SIZE]; Buffer.BlockCopy(BitConverter.GetBytes(header.netId), 0, buffer, 0, 2); Buffer.BlockCopy(BitConverter.GetBytes(header.number), 0, buffer, 2, 2); Buffer.BlockCopy(BitConverter.GetBytes(header.option), 0, buffer, 4, 2); Buffer.BlockCopy(BitConverter.GetBytes(header.checksum), 0, buffer, 6, 2); return(buffer); }
public NetHeader ByteArrayToNetHeader(byte[] data) { NetHeader nh = new NetHeader(); nh.netId = BitConverter.ToUInt16(data, 0); nh.number = BitConverter.ToUInt16(data, 2); nh.option = BitConverter.ToUInt16(data, 4); nh.checksum = BitConverter.ToUInt16(data, 6); return(nh); }
public void AppendReceivedMessage(NetSocket socket, byte[] buffer, int size) { outTime = 0; isConnected = true; NetHeader nh = NetBase.ByteArrayToNetHeader(buffer); // we are waiting for received confirmation from the other side if ((nh.option & NetBase.NET_OPTN_CONFIRMED) > 0) { if (nh.number == confirmNumber && nh.checksum == confirmChecksum) { Debug.Log("Info: Message number has been confirmed from other side!"); confirmNumber = 0; // confirmed retryTime = 0; // remove the message from the sending list m_sendingPacks.RemoveAt(0); } else { // do nothing !! } } else { // replay to sender that safe message has been received if ((nh.option & NetBase.NET_OPTN_SAFESEND) > 0) { NetPacket tmp = new NetPacket(); tmp.header = nh; tmp.header.option = NetBase.NET_OPTN_CONFIRMED; socket.Send(tmp, dest); } // create message container and append it to the list if (nh.number != recvNumber) { recvNumber = nh.number; NetPacket np = new NetPacket(); np.header = nh; np.data = new byte[size - NetBase.NET_HEADER_SIZE]; Buffer.BlockCopy(buffer, NetBase.NET_HEADER_SIZE, np.data, 0, np.data.Length); // add it to the received list m_receivedPacks.Add(np); //sx_print( L"message received header [NO: %d OP: %d CH: %d]\n", np.header.number, np.header.option, np.header.checksum ); } } }
internal static NetHeader Create(NetChannelReliable chan, uint time) { var header = new NetHeader { AckHistory = chan.AckHistory, AckSequence = chan.NewestRemoteSequence, ObjSequence = chan.LocalSequence, SendTime = time }; if (chan.LastReceiveTime > time) { header.AckTime = (ushort)Mathf.Clamp(time - chan.LastReceiveTime, 0, 6000); } return header; }
/// <summary> Removes acked messages from the send window, releases the stream, updates connection ping, and /// increments the Delivered stat. </summary> private void MessageDelivered(int index, NetHeader header) { Delivered++; NetStream strm = reliableWindow[sendWindow[index]]; if (header.AckTime > 0) { Connection.UpdatePing(NetTime.Milliseconds(), sendWindowTime[index], header.AckTime); } reliableWindow.Remove(sendWindow[index]); sendWindow.RemoveAt(index); sendWindowTime.RemoveAt(index); strm.Release(); }
/// <summary> Prepares the outgoing reliable stream: Writes the reliable bit & reliable header, /// sets stream parameters, and updates send stats. </summary> private NetHeader WriteHeader() { sendStream.Connection = Connection; sendStream.Socket = Connection.Socket; sendStream.WriteBool(true); var header = NetHeader.Create(this, NetTime.Milliseconds()); header.ToStream(sendStream); ReceivedSinceLastSend = 0; Sent++; return(header); }
internal static NetHeader Create(NetChannelReliable chan, uint time) { var header = new NetHeader { AckHistory = chan.AckHistory, AckSequence = chan.NewestRemoteSequence, ObjSequence = chan.LocalSequence, SendTime = time }; if (chan.LastReceiveTime > time) { header.AckTime = (ushort)Mathf.Clamp(time - chan.LastReceiveTime, 0, 6000); } return(header); }
/// <summary> Acknowledges and updates the remote sequence. </summary> private void AckReceived(NetHeader header) { int newestDist = NetMath.SeqDistance(header.ObjSequence, NewestRemoteSequence); // If the sequence is newest, shift the buffer and apply ack bit: if (newestDist > 0) { AckHistory = (AckHistory << newestDist) | 1UL; NewestRemoteSequence = header.ObjSequence; } // Else, shift the ack bit and apply to buffer: else { AckHistory |= 1UL << -newestDist; } LastReceiveTime = NetTime.Milliseconds(); ReceivedSinceLastSend++; Received++; }
/// <summary> Detects acknowledged and lost messages. </summary> private void AckDelivered(NetHeader header) { for (int i = 0; i < sendWindow.Count; i++) { int seqDist = NetMath.SeqDistance(sendWindow[i], header.AckSequence); // This AckSequence is older than the sendWindow's, not useful: if (seqDist > 0) break; // AckHistory has rolled over without acking this message; Ordered reliable is broken: if (seqDist <= -64) Connection.Disconnect(); // If the seqDistance corresponds to a true bit in the AckHistory, message delivered/acked: else if (IsAcked(header.AckHistory, seqDist)) { MessageDelivered(i, header); i--; // Since the sendWindow count will decrease, the index needs to be adjusted. } // The seqDist is still within the send window, but if too much time has passed, assume lost: else if (NetTime.Milliseconds() - sendWindowTime[i] > 333) MessageLost(i); } }
public void Run() { RC4Encryption rc4Server = new RC4Encryption(); RC4Encryption rc4Client = new RC4Encryption(); rc4Server.makeSBox("zhangyawei"); rc4Client.makeSBox("zhangyawei"); IPAddress ip = IPAddress.Parse("127.0.0.1"); Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { clientSocket.Connect(new IPEndPoint(ip, 26001)); Debug.logger.Log("connect Success."); } catch { Debug.logger.Log("connect Failed"); return; } if (true) { ClientAuthReq req = new ClientAuthReq("test", "123"); var binData = req.__encode().ToArray(); //binData = rc4Client.encryption(binData, binData.Length()); var sendData = new System.Collections.Generic.List <byte>(); NetHeader head = new NetHeader(); head.packLen = (UInt32)(4 + 2 + 2 + binData.Length); head.protoID = Proto4z.ClientAuthReq.getProtoID(); sendData.AddRange(head.__encode()); sendData.AddRange(binData); clientSocket.Send(sendData.ToArray()); var recvBytes = new byte[2000]; uint curLen = 0; uint needLen = 4 + 2 + 2; //暂时分两段读 后面要改buff接收提高效率 uint recvLen = 0; NetHeader recvHead = new NetHeader(); do { recvLen = (uint)clientSocket.Receive(recvBytes, (int)curLen, (int)needLen, System.Net.Sockets.SocketFlags.None);//第一段 if (recvLen == 0) { // remote close socket. return; } curLen += recvLen; needLen -= recvLen; if (needLen == 0 && curLen == 4 + 2 + 2) ////第一段 完成 { int pos = 0; recvHead.__decode(recvBytes, ref pos); needLen = recvHead.packLen - 4 - 2 - 2; //设置第二段 } else if (needLen == 0) //第二段完成 { if (recvHead.protoID == Proto4z.ClientAuthResp.getProtoID()) { ClientAuthResp result = new ClientAuthResp(); int pos = 4 + 2 + 2; result.__decode(recvBytes, ref pos); Debug.logger.Log("ClientAuthResp: account=" + result.account + ", token=" + result.token + ",retCode=" + result.retCode); int t = 0; t++; } else if (true) //other proto { } break; //一个协议接收处理完毕后break } recvLen = 0; } while (true); } }
public void Run(byte[] binData) { IPAddress ip = IPAddress.Parse("127.0.0.1"); Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { clientSocket.Connect(new IPEndPoint(ip, 8081)); //zsummerX/example/frameStressTest server default port Console.WriteLine("connect Success."); } catch { Console.WriteLine("connect Failed"); return; } do { var sendData = new System.Collections.Generic.List <byte>(); NetHeader head = new NetHeader(); head.packLen = (UInt32)(4 + 2 + 2 + binData.Length); head.protoID = Proto4z.EchoPack.getProtoID(); sendData.AddRange(head.__encode()); sendData.AddRange(binData); clientSocket.Send(sendData.ToArray()); var recvBytes = new byte[2000]; uint curLen = 0; uint needLen = 4 + 2 + 2; uint recvLen = 0; NetHeader recvHead = new NetHeader(); do { recvLen = (uint)clientSocket.Receive(recvBytes, (int)curLen, (int)needLen, System.Net.Sockets.SocketFlags.None); if (recvLen == 0) { return; } curLen += recvLen; needLen -= recvLen; if (needLen == 0 && curLen == 4 + 2 + 2) //head already read finish { int pos = 0; recvHead.__decode(recvBytes, ref pos); needLen = recvHead.packLen - 4 - 2 - 2; } else if (needLen == 0) { if (recvHead.protoID == Proto4z.EchoPack.getProtoID()) { Proto4z.EchoPack result = new Proto4z.EchoPack(); int pos = 4 + 2 + 2; result.__decode(recvBytes, ref pos); //System.Console.WriteLine("echo =" + result.text.val); } break; } recvLen = 0; } while (true); } while (true); }
public void AppendReceivedMessage(byte[] buffer, int size) { outTime = 0; isConnected = true; byte[] headerBuffer = new byte[net.NET_HEADER_SIZE]; Buffer.BlockCopy(buffer, 0, headerBuffer, 0, net.NET_HEADER_SIZE); NetHeader nh = net.ByteArrayToNetHeader(buffer); // we are waiting for received confirmation from the other side if ((nh.option & net.NET_OPTN_CONFIRMED) > 0) { if (nh.number == confirmNumber && nh.checksum == confirmChecksum) { //sx_print(L"Info: Message number %d has been confirmed from other side!\n", confirmNumber); confirmNumber = 0; // confirmed retryTime = 0; // remove the message from the sending list m_sendingPacks.RemoveAt(0); } else { // do nothing !! } } else { // replay to sender that safe message has been received if ((nh.option & net.NET_OPTN_SAFESEND) > 0) { NetPackage tmp = new NetPackage(net.NET_HEADER_SIZE, net.NET_BUFF_SIZE); tmp.header = nh; tmp.header.option = net.NET_OPTN_CONFIRMED; byte[] tmpBuf = net.NetHeaderToByteArray(tmp.header); Buffer.BlockCopy(tmpBuf, 0, tmp.data, 0, net.NET_HEADER_SIZE); net.socket.Send(dest, tmp.data, tmp.size); } // create message container and append it to the list if (nh.number != recvNumber) { recvNumber = nh.number; NetPackage np = new NetPackage(net.NET_HEADER_SIZE, net.NET_BUFF_SIZE); np.size = size; np.header = nh; Buffer.BlockCopy(buffer, 0, np.data, 0, size); // add it to the received list m_receivedPacks.Add(np); //sx_print( L"message received header [NO: %d OP: %d CH: %d]\n", np.header.number, np.header.option, np.header.checksum ); } } }
public void Run(byte[] binData) { IPAddress ip = IPAddress.Parse("127.0.0.1"); Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { clientSocket.Connect(new IPEndPoint(ip, 8081)); //zsummerX/example/frameStressTest server default port Console.WriteLine("connect Success."); } catch { Console.WriteLine("connect Failed"); return; } do { var sendData = new System.Collections.Generic.List<byte>(); NetHeader head = new NetHeader(); head.packLen = (UInt32)(4 + 2 + 2 + binData.Length); head.protoID = Proto4z.EchoPack.getProtoID(); sendData.AddRange(head.__encode()); sendData.AddRange(binData); clientSocket.Send(sendData.ToArray()); var recvBytes = new byte[2000]; uint curLen = 0; uint needLen = 4 + 2 + 2; uint recvLen = 0; NetHeader recvHead = new NetHeader(); do { recvLen = (uint)clientSocket.Receive(recvBytes, (int)curLen, (int)needLen, System.Net.Sockets.SocketFlags.None); if (recvLen == 0) { return; } curLen += recvLen; needLen -= recvLen; if (needLen == 0 && curLen == 4 + 2 + 2) //head already read finish { int pos = 0; recvHead.__decode(recvBytes, ref pos); needLen = recvHead.packLen - 4 - 2 - 2; } else if (needLen == 0) { if (recvHead.protoID == Proto4z.EchoPack.getProtoID()) { Proto4z.EchoPack result = new Proto4z.EchoPack(); int pos = 4+2+2; result.__decode(recvBytes, ref pos); //System.Console.WriteLine("echo =" + result.text.val); } break; } recvLen = 0; } while (true); } while (true); }
/// <summary> Adds an out-of-order datagram to the buffer to await future delivery. </summary> private void BufferOutOfOrder(int seqDist, NetStream strm, NetHeader header) { if (recvBuffer.Count >= 512) { Connection.Disconnect(); return; } if (recvBufferSeqDist.Contains(seqDist)) { strm.Release(); return; } // Ack history window is only 64 bits, so only ack if within window: if (seqDist < 64) { AckReceived(header); AckDelivered(header); } else strm.Pos = 1; // Reset to 1 so header can be reprocessed when seqDist < 64 recvBuffer.Add(strm); recvBufferSeqDist.Add(seqDist); }
/// <summary> Acknowledges and updates the remote sequence. </summary> private void AckReceived(NetHeader header) { int newestDist = NetMath.SeqDistance(header.ObjSequence, NewestRemoteSequence); // If the sequence is newest, shift the buffer and apply ack bit: if (newestDist > 0) { AckHistory = (AckHistory << newestDist) | 1UL; NewestRemoteSequence = header.ObjSequence; } // Else, shift the ack bit and apply to buffer: else AckHistory |= 1UL << -newestDist; LastReceiveTime = NetTime.Milliseconds(); ReceivedSinceLastSend++; Received++; }
/// <summary> Removes acked messages from the send window, releases the stream, updates connection ping, and /// increments the Delivered stat. </summary> private void MessageDelivered(int index, NetHeader header) { Delivered++; NetStream strm = reliableWindow[sendWindow[index]]; if (header.AckTime > 0) Connection.UpdatePing(NetTime.Milliseconds(), sendWindowTime[index], header.AckTime); reliableWindow.Remove(sendWindow[index]); sendWindow.RemoveAt(index); sendWindowTime.RemoveAt(index); strm.Release(); }