簡體   English   中英

連接恢復后報錯 Socket C#

[英]Error after connection restored Socket C#

我正在將文件分塊上傳到服務器。 如果你暫時斷開客戶端和服務器之間的連接,然后再恢復,服務器在嘗試從客戶端接收數據時會拋出錯誤:

嘗試建立連接未成功,因為在要求的時間內未從另一台計算機收到所需的響應,或者由於來自已連接計算機的錯誤響應而終止了已建立的連接

這發生在以下情況:如果我向服務器發送另一個塊並等待服務器的響應,則服務器此時處理請求,將響應發送給客戶端並等待下一個請求。 如果在向服務器發出請求后終止連接,並在 15 秒后恢復連接,則會出現錯誤。

從客戶端發送代碼的塊:

chunk = reader.ReadBytes(chunkSize);
bytesToRead -= chunkSize;

var packet = packetService.CreatePacket(new ServerPacket
{
  Command = CommandsNames.UploadDataCommand,
  ClientId = clientId,
  Payload = uploadingService.GetUploadDataPayload(
    chunk,
    uploadingHash),
  PayloadParts = new List<int>
    {
      Encoding.Unicode.GetByteCount(uploadingHash),
        chunk.Length
    }
});

await dataTransitService.SendDataAsync(_socket, packet);
var response = await dataTransitService
   .ReadDataAsync(
     _socket,
     chunkSize,
     p => packetService.ParsePacket(p));

SendDataAsync 方法:

public async Task SendDataAsync(
            Socket socket, 
            IEnumerable<byte> data)
        {
            if (data != null && data.Any())
            {
                await socket.SendAsync(
                    new ArraySegment<byte>(data.ToArray()),
                    SocketFlags.None);
            }
        }

ReadDataAsync 方法:

public async Task<T> ReadDataAsync<T>(
            Socket socket, 
            int chunkSize,
            Func<IEnumerable<byte>, T> parsePacket)
        {
            var data = new ArraySegment<byte>(new byte[chunkSize]);
            var receivedPacket = new List<byte>();

            do
            {
                var bytes = await socket.ReceiveAsync(data, SocketFlags.None);

                if (data.Array != null)
                {
                    receivedPacket.AddRange(data.Array);
                }
            }
            while (socket.Available > 0);

            return parsePacket(receivedPacket);
        }

客戶端套接字配置:

var (port, address) = (
                    _configurationSection["port"],
                    _configurationSection["address"]);

            var ipPoint = new IPEndPoint(
                IPAddress.Parse(address),
                Int32.Parse(port));
            socket = new Socket(
                AddressFamily.InterNetwork, 
                SocketType.Stream, ProtocolType.Tcp);

服務器套接字配置:

 var section = _configuration.GetSection("listener");
            var (address, port) = (section["address"], section["port"]);
            var listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            var ipPoint = new IPEndPoint(IPAddress.Parse(address), Int32.Parse(port));

            try
            {
                listenSocket.Bind(ipPoint);
                listenSocket.Listen(20);
               
                Console.WriteLine("Waiting for connections...");
             
                var socket = listenSocket.Accept();                
                await _serverProcess.ProcessAsync(socket, StopServer);

如果在向服務器發出請求后終止連接,並在 15 秒后恢復連接,則會出現錯誤。

如果您拔下網線, Windows 通過該 NIC 告訴 sockets 他們已斷開連接 否則(假設您的電纜仍然插入,但其間的電纜、交換機或路由器停止工作),您需要在該插座上發送或接收,以便它檢測到它已斷開連接。

請參閱如何檢查 C# 中的套接字是否連接/斷開? .

一旦斷開連接,套接字將無法恢復。 您需要檢測此狀態,啟動新連接並告訴您的服務器您要繼續先前的傳輸。 我們不知道您的協議是否理解這一點。

另外: IEnumerable<byte> datadata.Any()new ArraySegment<byte>(data.ToArray()) - 為什么?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM