主頁 > 區塊鏈 > 什么會導致TCP套接字接收到0個位元組,但在異步套接字服務器中卻有位元組可用?

什么會導致TCP套接字接收到0個位元組,但在異步套接字服務器中卻有位元組可用?

2021-10-14 03:45:24 區塊鏈

我有一個基于微軟提供的例子的C#、.NET資料服務器:

https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socketasynceventargs?view=net-5.0

我已經讓這個資料服務器作業了很多年,有一個簡單的設備監聽器來處理發送的資料。以前的用例是設備向服務器發送資料,服務器發回一個回應,然后設備關閉連接。這一點運行良好。

我正在添加讓設備在收到回應后發送額外資料的功能。這個功能在第一次時運行良好。但是在第一次之后,我得到的后續訊息中,傳輸的位元組數為零,SocketError仍被設定為Success,但是Available顯示了客戶端設備發送的適當的資料量。所以,資料服務器將其視為一個關閉的連接。我不明白為什么服務器沒有收到資料,即使WireShark顯示了傳輸的資料,而且套接字上的可用位元組數顯示它們正在等待被接收。這就像服務器進入了一個糟糕的狀態,它實際上無法接收正在等待的位元組。

下面是資料服務器的代碼:

using System;
using System.Collections;
using System.Collections.Generic;

使用System.Linq.Options; 使用System.Linq.Options
使用System.Net;
using System.Net.Sockets;



namespaceDeviceListener
{
    class SocketAsyncUserToken {
    {
        public Socket Socket。
        public DateTime AcceptedAt;
        public DateTime LastUpdate;
        public bool Closed = falsepublic int TotalBytes = 0;
        public string DeviceId = null;
        public byte[] ReceiveBuffer = new byte[2048] 。
        public byte[] SendBuffer = new byte[2048] 。
    }

    public enum DataServerEventTypes
    {
        None = 0,
        未知。
        錯誤。
        警告。
        資訊。
        服務器已啟動。
        服務器停止了。
        連接已接受。
        連接已關閉。
        連接拒絕。
        收到的資料。
        資料發送。
        訊息處理
    }

    public class DataServerEventArgs : EventArgs
    {
        public DataServerEventTypes EventType;
        public string DeviceId;
        public string Details;
        public Exception 例外。
    }

    //為套接字服務器實作了連接邏輯。  
    //接受連接后,所有從客戶端讀取的資料//被送回客戶端。讀取并回傳給客戶端的模式/span>//繼續進行,直到客戶端斷開連接。
    public class SocketAsyncServer 
    {
        private int m_numConnections; //the max number of connections the sample is designed to handle simultaneously 
        private int m_receiveBufferSize;//用于每個套接字I/O操作的緩沖區大小。
        SocketAsyncBufferManager m_bufferManager; //代表一個大型的可重復使用的緩沖區集,用于所有套接字操作const int opsToPreAlloc = 2; //讀、寫(不要為接受分配緩沖空間)
        Socket listenSocket; //用于監聽進入的連接請求的套接字///可重復使用的SocketAsyncEventArgs物件池,用于寫、讀和接受套接字操作。
        SocketAsyncEventArgsPool m_readWritePool。
        int m_totalBytesRead; //服務器收到的總#位元組的計數器int m_numConnectedSockets; //連接到服務器的客戶總數。
        Semaphore m_maxNumberAcceptedClients。
        string m_AuthenticationId;
        List<SocketAsyncEventArgs> m_AcceptedConnections。

        public event EventHandler<DataServerEventArgs> EventNotify;

        //創建一個未初始化的服務器實體。  
        //要啟動服務器監聽連接請求//呼叫Init方法,然后是Start方法//
        //<param name="numConnections">樣本被設計為同時處理的最大連接數</param>
        // <param name="receiveBufferSize">為每個套接字I/O操作使用的緩沖區大小</param>public SocketAsyncServer(intnumConnections, int receiveBufferSize, string authenticationId)。
        {
            m_totalBytesRead = 0;
            m_numConnectedSockets = 0;
            m_numConnections = numConnections。
            m_receiveBufferSize = receiveBufferSize;
            m_AuthenticationId = authenticationId。
            //分配緩沖區,使最大數量的套接字可以有一個未完成的讀取和//寫同時發布到套接字上 
            m_bufferManager = new SocketAsyncBufferManager(receiveBufferSize * numConnections * opsToPreAlloc, receiveBufferSize)。

            m_readWritePool = new SocketAsyncEventArgsPool(numConnections)。
            m_maxNumberAcceptedClients = new Semaphore(numConnections, numConnections);
            m_AcceptedConnections = new List<SocketAsyncEventArgs>()。
        }

        // <summary>
        //當一項作業完成時觸發的事件處理器。
        // </summary>/span>
        // <param name="e"></param>
        public void OnEventNotify(DataServerEventArgs e)
        {
            EventNotify?.Invoke(this, e) 。
        }

        ///通過預分配可重用的緩沖區和來初始化服務器。
        // context物件。 這些物件不需要預先分配
        //或重復使用,但這樣做是為了說明API如何//或重復使用。
        //很容易被用來創建可重用的物件以提高服務器性能。
        //
        public void Init
        {
            ///分配一個大的位元組緩沖區,所有的I/O操作都使用其中的一塊。 這保證了
            //防止記憶體碎片化。
            m_bufferManager.InitBuffer()。

            //預分配SocketAsyncEventArgs物件池
            SocketAsyncEventArgs readWriteEventArg;

            for (int i = 0; i < m_numConnections; i  )
            {
                //Pre-allocate a set of reusable SocketAsyncEventArgs.
                readWriteEventArg = new SocketAsyncEventArgs()。
                readWriteEventArg.Completed  = new EventHandler<SocketAsyncEventArgs>(SendReceive_Completed)。
                readWriteEventArg.UserToken = new SocketAsyncUserToken()。

                //從緩沖池中分配一個位元組的緩沖區給SocketAsyncEventArg物件。
                m_bufferManager.SetBuffer(readWriteEventArg)。

                //將SocketAsyncEventArg添加到池中
                m_readWritePool.Push(readWriteEventArg)。
            }
        }

        //啟動服務器,使其監聽//進入的連接請求。    
        //
        // <param name="localEndPoint">服務器將監聽的端點//用于連接請求的</param> 
        public bool StartIPEndPoint localEndPoint
        {
            DataServerEventArgs args = new DataServerEventArgs();
            args.EventType = DataServerEventTypes.ServerStarted;
            args.Details = "Server is starting on port "   localEndPoint.Port   "。"。
            OnEventNotify(args);

            //創建監聽傳入連接的socket。
            listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)。
            listenSocket.Bind(localEndPoint)。
            //啟動服務器,聽積壓的100個連接。
            listenSocket.Listen(100)。

            ///在監聽套接字上發布接受信號。
            StartAccept(null)。

            return true。
        }

        public bool Stop() 
        {
            List<SocketAsyncEventArgs> connectionsToClose = new List<SocketAsyncEventArgs>()。
            foreach (SocketAsyncEventArgs s  in m_AcceptedConnections)
            {
                if (s.ConnectSocket != null)
                {
                    DataServerEventArgs args = new DataServerEventArgs()。
                    args.EventType = DataServerEventTypes.ConnectionClosed;
                    args.Details = "服務器已強制關閉套接字"   s.ConnectSocket.Handle.ToInt32()   " 由于關閉。
                    OnEventNotify(args);
                    connectionsToClose.Add(s)。
                }
            }
            if (connectionToClose.Count > 0)
            {
                foreach (SocketAsyncEventArgs s in connectionsToClose)
                {
                    CloseClientSocket(s)。
                }
            }
            return true。
        }

        //開始一個操作,接受來自客戶端的連接請求//
        // <param name="acceptEventArg">發布時要使用的背景關系物件//在服務器的監聽套接字上的接受操作</param> 
        public void StartAcceptSocketAsyncEventArgs acceptEventArg
        {
            if (acceptEventArg == null)
            {
                acceptEventArg = new SocketAsyncEventArgs();
                acceptEventArg.Completed  = new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed)。
            }
            else[/span
            {
                // socket必須被清除,因為背景關系物件被重新使用。
                acceptEventArg.AcceptSocket = null;
            }

            DateTime currentTime = DateTime.Now;
            SocketAsyncUserToken token = null;
            TimeSpan ts = new TimeSpan(0, 1, 0)。
            List<SocketAsyncEventArgs> connectionsToClose = new List<SocketAsyncEventArgs>()。
            foreach (SocketAsyncEventArgs s in m_AcceptedConnections)
            {
                token = (SocketAsyncUserToken)s.UserToken。
                if (currentTime - token.LastUpdate > ts)
                {
                    DataServerEventArgs args = new DataServerEventArgs();
                    args.EventType = DataServerEventTypes.ConnectionClosed;
                    args.Details = "服務器已強制關閉套接字"   token.Socket.Handle.ToInt32()   " 由于超時,"。
                    OnEventNotify(args);
                    connectionsToClose.Add(s)。
                }
            }
            if (connectionsToClose.Count > 0)
            {
                foreach (SocketAsyncEventArgs s in connectionsToClose)
                {
                    CloseClientSocket(s)。
                }
            }
            m_maxNumberAcceptedClients.WaitOne()。
            bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg)。
            if (!willRaiseEvent)
            {
                ProcessAccept(acceptEventArg)。
            }
        }

        //這個方法是與Socket.AcceptAsync相關的回呼方法//操作,并在接受操作完成后被呼叫//
        void AcceptEventArg_Completed(>sender, SocketAsyncEventArgs e) 
        {
            ProcessAccept(e)。
        }

        private void ProcessAcceptSocketAsyncEventArgs e。
        {
            Interlocked.Increment(ref m_numConnectedSockets)。
            DataServerEventArgs args = new DataServerEventArgs();
            args.EventType = DataServerEventTypes.ConnectionAccepted。
            args.Details = "服務器在套接字上接受了一個連接"   e.AcceptSocket.Handle.ToInt32()   "。"。
            OnEventNotify(args);
            args.EventType = DataServerEventTypes.ConnectionAccepted;
            args.Details = "有"   m_numConnectedSockets   " 客戶端連接。"。
            OnEventNotify(args);

            //獲取已接受的客戶端連接的套接字,并將其放入中。
            //ReadEventArg物件的用戶令牌。
            SocketAsyncEventArgs readEventArgs = m_readWritePool.Pop()。
            SocketAsyncUserToken token = (SocketAsyncUserToken)readEventArgs.UserToken。
            token.Socket = e.AcceptSocket;
            token.AcceptedAt = DateTime.Now;
            token.LastUpdate = token.AcceptedAt;
            token.TotalBytes = 0;
            token.Closed = false;
            token.DeviceId = null;
            token.WaitingForControlResponse = false;

            m_AcceptedConnections.Add(readEventArgs)。

            //一旦客戶端被連接,就向連接發布一個接收bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs)。
            if (!willRaiseEvent)
            {
                ProcessReceive(readEventArgs)。
            }

            //接受下一個連接請求。
            StartAccept(e);
        }

        //每當套接字上的接收或發送操作完成時,就會呼叫這個方法//
        //<param name="e">與完成的接收操作相關的SocketAsyncEventArg</param>
        void SendReceive_Completed(object sender, SocketAsyncEventArgs e)
        {
            //確定哪種型別的操作剛剛完成并呼叫相關的處理程式switch (e.LastOperation)
            {
                case SocketAsyncOperation.Receive。
                    ProcessReceive(e)。
                    break;
                case SocketAsyncOperation.Send。
                    ProcessSend(e)。
                    break;
                default:
                    throw new ArgumentException("套接字上最后完成的操作不是接收或發送")。
            }

        }

        //此方法在異步接收操作完成時被呼叫。 
        //如果遠程主機關閉了連接,那么套接字就會被關閉。  
        //
        private void ProcessReceiveSocketAsyncEventArgs e
        {
            //檢查遠程主機是否關閉連接。
            SocketAsyncUserToken token = (SocketAsyncUserToken)e.UserToken。
            if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
            {
                //增加服務器收到的總位元組數。
                Interlocked.Add(ref m_totalBytesRead, e.BytesTransferred) 。
                Buffer.BlockCopy(e.Buffer, e.Offset, token.ReceiveBuffer, token.TotalBytes, e.BytesTransferred) 。

                byte[] raw = new byte[e.BytesTransferred] 。

                Array.Copy(e.Buffer, e.Offset, raw, 0, e.BytesTransferred)。

                string raw_bytes = BitConverter.ToString(raw)。
                token.TotalBytes  = e.BytesTransferred;
                token.LastUpdate = DateTime.Now;

                DataServerEventArgs args = null;
                
                args = new DataServerEventArgs()。
                args.EventType = DataServerEventTypes.DataReceived;
                args.Details = "Raw Bytes:
"   raw_bytes   "
服務器在套接字"   token.TotalBytes   "位元組數"   token.Socket.Handle.ToInt32()   "。
                OnEventNotify(args);
                
                bool eot = falseint index = 0;
                for (int i = e.Offset; i < e.Offset   e.BytesTransferred; i  )
                {
                    if (e.Buffer[i] == 4)
                    {
                        //跳過eot字符。
                        index  ;
                        
                        eot = true;
                        break。
                    }
                    index  ;
                }

                //檢查傳輸結束(EOT)的位元組if (eot)
                {
                    string messageStr = null;
                    string messageType = null;

                    messageStr = System.Text.Encoding.ASCII.GetString(token.ReceiveBuffer, 0, token.TotalBytes) 。
                    token.DeviceId = messageStr.Substring(0, 3)。
                    messageType = messageStr.Substring(3, 3) 。

                    int count = 0;

                    //生成回應; //生成回應。
                    count = Message.Response(token);

                    token.TotalBytes = 0;

                    //發送回應。
                    e.SetBuffer(token.SendBuffer, 0, count)。

                    args = new DataServerEventArgs()。
                    args.EventType = DataServerEventTypes.DataSent;
                    args.DeviceId = token.DeviceId;
                    args.Details = "發送回應的"   count   " bytes for "   token.DeviceId   " on socket "   token.Socket.Handle.ToInt32()   "。
                    OnEventNotify(args);
                    bool willRaiseEvent = token.Socket.SendAsync(e)。
                    if (!willRaiseEvent)
                    {
                        ProcessSend(e);
                    }             
                }
                else(!willRaiseEvent) { ProcessSend(e); }
                {
                    bool willRaiseEvent = token.Socket.ReceiveAsync(e)。
                    if (!willRaiseEvent)
                    {
                        ProcessReceive(e);
                    }
                }
            }
            else if (token.Socket.Available > 0)
            {
                //為什么資料沒有被接收到?
                var args = new DataServerEventArgs() 。
                args.EventType = DataServerEventTypes.Error;
                args.Details = "未收到資料,但在套接字"/span>   token.Socket.Handle.ToInt32()   ",已傳輸。"   e.BytesTransferred   ", Available: "   token.Socket.Available   ", SocketError: "   e.SocketError   "。"。
                OnEventNotify(args);
                 
                //這將導致堆疊溢位,因為ByteTransferred始終為0/*
                bool willRaiseEvent = token.Socket.ReceiveAsync(e)。
                如果(!willRaiseEvent)
                {
                    ProcessReceive(e);
                
                */
            }
            // SocketError.Success and e.BytesTransferred == 0 means client disconnected
            else
            {
                var args = new DataServerEventArgs();
                args.EventType = DataServerEventTypes.ConnectionClosed;
                args.Details = "Closing socket "   token.Socket.Handle.ToInt32()   ", "   e.SocketError   "。
                OnEventNotify(args);
                CloseClientSocket(e)。
            }
        }

        //此方法在異步發送操作完成時被呼叫。  
        //該方法在套接字上發出另一個接收,以讀取任何額外的//從客戶端發送的資料//
        //<param name="e"></param> 
        private void ProcessSendSocketAsyncEventArgs e
        {
            if (e.SocketError == SocketError.Success)
            {
                SocketAsyncUserToken token = (SocketAsyncUserToken)e.UserToken。
                //讀取從客戶端發送的下一個資料塊bool willRaiseEvent = token.Socket.ReceiveAsync(e)。
                if (!willRaiseEvent)
                {
                    ProcessReceive(e);
                }
            }
            else(!willRaiseEvent) { ProcessReceive(e); }
            {
                CloseClientSocket(e);
            }
        }

        private void CloseClientSocketSocketAsyncEventArgs e
        {
            SocketAsyncUserToken token = e.UserToken  as SocketAsyncUserToken;

            //關閉與客戶端相關的套接字try 
            {
                if (token.Closed)
                {
                    return;
                }
                else; }
                {
                    token.Closed = true;
                }
                token.Socket.Shutdown(SocketShutdown.Send)。
                DataServerEventArgs args1 = new DataServerEventArgs();
                args1.EventType = DataServerEventTypes.ConnectionClosed;
                args1.Details = "服務器已經關閉了套接字"   token.Socket.Handle.ToInt32()   " 成功。
                OnEventNotify(args1);
            }
            //throws if client process has already closed new DataServerEventArgs();
                args2.EventType = DataServerEventTypes.ConnectionClosed;
                args2.Details = "套接字"   token.Socket.Handle.ToInt32()   " 已經關閉了。"。
                OnEventNotify(args2);
                return;
            }
            token.Socket.Close()。

            //Decrement the counter keeping track of the total number of clients connected to the server.
            Interlocked.Decrement(ref m_numConnectedSockets)。
            m_maxNumberAcceptedClients.Release()。
            DataServerEventArgs args = new DataServerEventArgs();
            args.EventType = DataServerEventTypes.ConnectionClosed;
            args.Details = "有"   m_numConnectedSockets   " 客戶端連接。"。
            OnEventNotify(args);

            m_AcceptedConnections.Remove(e)。

            //釋放SocketAsyncEventArg,以便它們可以被另一個客戶端重新使用。
            m_readWritePool.Push(e)。
        }
    }    

對于為什么會出現這個問題,有什么想法嗎?只要只有一個來回的傳輸,一切都很正常。當同一連接上有第二次交換時,就會出現問題。

編輯:添加了記錄的輸出來證明這個問題:

服務器正在啟動15027。
服務器已經接受了一個連接套接字1068.。
有1個客戶連接。
原始位元組。
7E-39-3901-02-31-03- 30-35-2-03-2-5B-30-39-2F-31-34-2F-32- 31-20-31- 36-3A-33-37-3A-32-38-20-33-5D- 20-44-65-76-69-63-65- 20-73-74- 61-72-74-75-70-2E-20-5B-30-5 D-03-04
服務器總共讀取了55位元組套接字1068。
收到來自 ~99 on socket 1068. 的通知型別的訊息。
訊息處理回應。DRX,09/14/21 163728 3 for ~99 on socket1068. 
發送28位元組的回應for ~99 on socket 1068。
關閉插座1068,成功。
服務器已經成功關閉了套接字1068。
有0個客戶連接。
服務器已經接受了一個連接套接字1092.。
有1個客戶連接。
原始位元組。
7E-39-39-03-04
服務器總共讀取了5位元組套接字1092。
收到來自 ~99 on socket 1092. 的ControlRequest型別的訊息。
訊息處理回應。1, D1L for ~99 on socket 1092.
發送7位元組的回應 for ~99 on socket 1092.
原始位元組。
44314C-04
服務器總共讀取了4位元組套接字1092。
發送0位元組的回應 for ~99 on socket  1092.
關閉插座1092,成功。
服務器已經成功關閉了套接字1092。
有0個客戶連接。
服務器已經接受了一個連接套接字2140.。
有1個客戶連接。
資料沒有轉移,但可用的套接字2140,已轉移。0, Available: 61, SocketError: 成功。
服務器已經接受了一個連接套接字2244.。
有2個客戶連接。
原始位元組。
7E-39-39-03-04
服務器總共讀取了5位元組套接字2244。
收到來自 ~99 on socket 2244. 的ControlRequest型別的訊息。
訊息處理回應。1, D1L for ~99 on socket 2244.
發送7位元組的回應 for ~99 on 插座 2244.
原始位元組。
44314C-04
服務器總共讀取了4位元組套接字2244。
發送0位元組的回應 for ~99 on socket 2244.
關閉插座2244,成功。
服務器已經成功關閉了套接字2244。
有1個客戶連接。
服務器已經接受了一個連接套接字2248.。
有2個客戶連接。
資料沒有轉移,但可用的套接字2248,已轉移。0, Available: 5, SocketError: 成功。
服務器已經接受了一個連接套接字2256.。
有3個客戶連接。
原始位元組。
7E-39-3902-05-06-02- 30-2E-30-30-30-35-35-35- 03-1C-02-30-2E-30-30-30-30-30-30- 03-13-02-31-2E-30-30-30- 30-30-30-03-1F-02-30-2E- 30-30-30-30-30-30-03- 44-02-2D-31-30-30-2E-30-30-03-04
服務器總共讀取了61位元組套接字2256。
收到DataSample型別的訊息 來自 ~99 on socket 2256.
訊息處理回應。DRX, Acknowledged for ~99 on socket2256.
發送21位元組的回應 for ~99 on socket 2256.
關閉插座2256,成功。
服務器已經成功關閉了套接字2256。
有2個客戶連接。
服務器已經強制關閉了套接字2140,因為超時了。
服務器已經成功關閉了套接字2140。
有1個客戶連接。
服務器已經接受了一個連接套接字2140.上。
有2個客戶連接。
資料沒有轉移,但可用的套接字2140,已轉移。0, Available: 5, SocketError: 成功。

uj5u.com熱心網友回復:

看起來你在做一個零位元組的接收--這在某些情況下對檢測資料何時可用很有用,而不需要為接收保留緩沖區。

int count = 0;
//...
e.SetBuffer(token.SendBuffer, 0, count) 。

使最后一個引數超過0--如果這是發送:確保你發送你打算發送的東西,如果這是用于接收:它需要是積極的,以實際接收資料(而不是僅僅檢測資料的存在)。如果你在連續的發送和接收中使用相同的引數:請確保你在每一次操作之前適當地設定緩沖區的長度。

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/311823.html

標籤:

上一篇:如何在Excel中創建復選框

下一篇:從flutter中的socket回傳一個值

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • JAVA使用 web3j 進行token轉賬

    最近新學習了下區塊鏈這方面的知識,所學不多,給大家分享下。 # 1. 關于web3j web3j是一個高度模塊化,反應性,型別安全的Java和Android庫,用于與智能合約配合并與以太坊網路上的客戶端(節點)集成。 # 2. 準備作業 jdk版本1.8 引入maven <dependency> < ......

    uj5u.com 2020-09-10 03:03:06 more
  • 以太坊智能合約開發框架Truffle

    前言 部署智能合約有多種方式,命令列的瀏覽器的渠道都有,但往往跟我們程式員的風格不太相符,因為我們習慣了在IDE里寫了代碼然后打包運行看效果。 雖然現在IDE中已經存在了Solidity插件,可以撰寫智能合約,但是部署智能合約卻要另走他路,沒辦法進行一個快捷的部署與測驗。 如果團隊管理的區塊節點多、 ......

    uj5u.com 2020-09-10 03:03:12 more
  • 谷歌二次驗證碼成為區塊鏈專用安全碼,你怎么看?

    前言 谷歌身份驗證器,前些年大家都比較陌生,但隨著國內互聯網安全的加強,它越來越多地出現在大家的視野中。 比較廣泛接觸的人群是國際3A游戲愛好者,游戲盜號現象嚴重+國外賬號安全應用廣泛,這類游戲一般都會要求用戶系結名為“兩步驗證”、“雙重驗證”等,平臺一般都推薦用谷歌身份驗證器。 后來區塊鏈業務風靡 ......

    uj5u.com 2020-09-10 03:03:17 more
  • 密碼學DAY1

    目錄 ##1.1 密碼學基本概念 密碼在我們的生活中有著重要的作用,那么密碼究竟來自何方,為何會產生呢? 密碼學是網路安全、資訊安全、區塊鏈等產品的基礎,常見的非對稱加密、對稱加密、散列函式等,都屬于密碼學范疇。 密碼學有數千年的歷史,從最開始的替換法到如今的非對稱加密演算法,經歷了古典密碼學,近代密 ......

    uj5u.com 2020-09-10 03:03:50 more
  • 密碼學DAY1_02

    目錄 ##1.1 ASCII編碼 ASCII(American Standard Code for Information Interchange,美國資訊交換標準代碼)是基于拉丁字母的一套電腦編碼系統,主要用于顯示現代英語和其他西歐語言。它是現今最通用的單位元組編碼系統,并等同于國際標準ISO/IE ......

    uj5u.com 2020-09-10 03:04:50 more
  • 密碼學DAY2

    ##1.1 加密模式 加密模式:https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html ECB ECB : Electronic codebook, 電子密碼本. 需要加密的訊息按照塊密碼的塊大小被分為數個塊,并對每個塊進 ......

    uj5u.com 2020-09-10 03:05:42 more
  • NTP時鐘服務器的特點(京準電子)

    NTP時鐘服務器的特點(京準電子) NTP時鐘服務器的特點(京準電子) 京準電子官V——ahjzsz 首先對時間同步進行了背景介紹,然后討論了不同的時間同步網路技術,最后指出了建立全球或區域時間同步網存在的問題。 一、概 述 在通信領域,“同步”概念是指頻率的同步,即網路各個節點的時鐘頻率和相位同步 ......

    uj5u.com 2020-09-10 03:05:47 more
  • 標準化考場時鐘同步系統推進智能化校園建設

    標準化考場時鐘同步系統推進智能化校園建設 標準化考場時鐘同步系統推進智能化校園建設 安徽京準電子科技官微——ahjzsz 一、背景概述隨著教育事業的快速發展,學校建設如雨后春筍,隨之而來的學校教育、管理、安全方面的問題成了學校管理人員面臨的最大的挑戰,這些問題同時也是學生家長所擔心的。為了讓學生有更 ......

    uj5u.com 2020-09-10 03:05:51 more
  • 位元幣入門

    引言 位元幣基本結構 位元幣基礎知識 1)哈希演算法 2)非對稱加密技術 3)數字簽名 4)MerkleTree 5)哪有位元幣,有的是UTXO 6)位元幣挖礦與共識 7)區塊驗證(共識) 總結 引言 上一篇我們已經知道了什么是區塊鏈,此篇說一下區塊鏈的第一個應用——位元幣。其實先有位元幣,后有的區塊 ......

    uj5u.com 2020-09-10 03:06:15 more
  • 北斗對時服務器(北斗對時設備)電力系統應用

    北斗對時服務器(北斗對時設備)電力系統應用 北斗對時服務器(北斗對時設備)電力系統應用 京準電子科技官微(ahjzsz) 中國北斗衛星導航系統(英文名稱:BeiDou Navigation Satellite System,簡稱BDS),因為是目前世界范圍內唯一可以大面積提供免費定位服務的系統,所以 ......

    uj5u.com 2020-09-10 03:06:20 more
最新发布
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:46:47 more
  • Hyperledger Fabric 使用 CouchDB 和復雜智能合約開發

    在上個實驗中,我們已經實作了簡單智能合約實作及客戶端開發,但該實驗中智能合約只有基礎的增刪改查功能,且其中的資料管理功能與傳統 MySQL 比相差甚遠。本文將在前面實驗的基礎上,將 Hyperledger Fabric 的默認資料庫支持 LevelDB 改為 CouchDB 模式,以實作更復雜的資料... ......

    uj5u.com 2023-04-16 07:28:31 more
  • .NET Core 波場鏈離線簽名、廣播交易(發送 TRX和USDT)筆記

    Get Started NuGet You can run the following command to install the Tron.Wallet.Net in your project. PM> Install-Package Tron.Wallet.Net 配置 public reco ......

    uj5u.com 2023-04-14 08:08:00 more
  • DKP 黑客分析——不正確的代幣對比率計算

    概述: 2023 年 2 月 8 日,針對 DKP 協議的閃電貸攻擊導致該協議的用戶損失了 8 萬美元,因為 execute() 函式取決于 USDT-DKP 對中兩種代幣的余額比率。 智能合約黑客概述: 攻擊者的交易:0x0c850f,0x2d31 攻擊者地址:0xF38 利用合同:0xf34ad ......

    uj5u.com 2023-04-07 07:46:09 more
  • Defi開發簡介

    Defi開發簡介 介紹 Defi是去中心化金融的縮寫, 是一項旨在利用區塊鏈技術和智能合約創建更加開放,可訪問和透明的金融體系的運動. 這與傳統金融形成鮮明對比,傳統金融通常由少數大型銀行和金融機構控制 在Defi的世界里,用戶可以直接從他們的電腦或移動設備上訪問廣泛的金融服務,而不需要像銀行或者信 ......

    uj5u.com 2023-04-05 08:01:34 more
  • solidity簡單的ERC20代幣實作

    // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; import "hardhat/console.sol"; //ERC20 同質化代幣,每個代幣的本質或性質都是相同 //ETH 是原生代幣,它不是ERC20代幣, ......

    uj5u.com 2023-03-21 07:56:29 more
  • solidity 參考型別修飾符memory、calldata與storage 常量修飾符C

    在solidity語言中 參考型別修飾符(參考型別為存盤空間不固定的數值型別) memory、calldata與storage,它們只能修飾參考型別變數,比如字串、陣列、位元組等... memory 適用于方法傳參、返參或在方法體內使用,使用完就會清除掉,釋放記憶體 calldata 僅適用于方法傳參 ......

    uj5u.com 2023-03-08 07:57:54 more
  • solidity注解標簽

    在solidity語言中 注釋符為// 注解符為/* 內容*/ 或者 是 ///內容 注解中含有這幾個標簽給予我們使用 @title 一個應該描述合約/介面的標題 contract, library, interface @author 作者的名字 contract, library, interf ......

    uj5u.com 2023-03-08 07:57:49 more
  • 評價指標:相似度、GAS消耗

    【代碼注釋自動生成方法綜述】 這些評測指標主要來自機器翻譯和文本總結等研究領域,可以評估候選文本(即基于代碼注釋自動方法而生成)和參考文本(即基于手工方式而生成)的相似度. BLEU指標^[^?88^^?^]^:其全稱是bilingual evaluation understudy.該指標是最早用于 ......

    uj5u.com 2023-02-23 07:27:39 more
  • 基于NOSTR協議的“公有制”版本的Twitter,去中心化社交軟體Damus

    最近,一個幽靈,Web3的幽靈,在網路游蕩,它叫Damus,這玩意詮釋了什么叫做病毒式營銷,滑稽的是,一個Web3產品卻在Web2的產品鏈上瘋狂傳銷,各方大佬紛紛為其背書,到底發生了什么?Damus的葫蘆里,賣的是什么藥? 注冊和簡單實用 很少有什么產品在用戶注冊環節會有什么噱頭,但Damus確實出 ......

    uj5u.com 2023-02-05 06:48:39 more