Сломанные сокеты в .NET? - PullRequest
       2

Сломанные сокеты в .NET?

2 голосов
/ 22 октября 2010

Вот действительно странная проблема: по-видимому, определенная последовательность байтов, которая преобразуется в ASCII "PUttttt", если она отправляется через сокет TCP, вообще не попадает в клиент.

Я включил пример кода, использованного для демонстрации проблемы ниже, в надежде, что кто-то может иметь представление о том, почему это происходит. Серверные и клиентские приложения были намеренно сокращены до простых консольных синхронных версий, чтобы упростить поиск и устранение неисправностей.

Ключевым аспектом проблемы являются данные, которые поступают в буфер отправки (строка «PUttttt»).

Сервер:

using System;      
using System.Net.Sockets;
using System.Net;

namespace ConsoleServer
{
    private static Socket mServer;
    private static byte[] fileBytes;
    private static int sent_total;

    static void Main(string[] args)
    {
        string hostName = "localhost";  //Dns.GetHostName();
        IPHostEntry ipHostInfo = Dns.GetHostEntry(hostName);
        IPAddress iaddr = null;
        for(int k = 0; k < ipHostInfo.AddressList.Length; k++)
            if (ipHostInfo.AddressList[k].AddressFamily == AddressFamily.InterNetwork)
            {
                iaddr = ipHostInfo.AddressList[k];
                break;
            }

        if (iaddr == null)
        {
            Console.WriteLine("Can not bind to any interface.. Server can not start");
            Console.ReadKey();
            return;
        }

        mServer = new Socket(iaddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        mServer.Bind(new IPEndPoint(iaddr, 8000));

        Console.WriteLine("Server: Bound to " + hostName + " (" + iaddr.ToString() + "):8000");
        mServer.Listen(1);

        Console.WriteLine("Server: Started. Awaiting connection.");

        Socket handler = mServer.Accept();
        handler.LingerState = new LingerOption(true, 5);

        Console.WriteLine("Server: A Client connected\r\nServer: sending data");

        string str = @"PUttttt";
        fileBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(str);

        SocketError errCode = SocketError.Success;
        int sent = handler.Send(fileBytes, 0, fileBytes.Length, SocketFlags.None, out errCode);
        sent_total += sent;
        Console.WriteLine("Server: Done sending. " + sent_total + " bytes (" + errCode.ToString() + ")");

        handler.Close();

        Console.WriteLine("Server: CLient Disconnected");

        Console.ReadKey();
    } 
   }
}

Клиент:

using System;
using System.Net.Sockets;
using System.Net;

namespace ConsoleClient
{
  class Program
  {
    private static int BUFFER_SIZE = 1024 * 1024;
    private static string SERVER_ADDR = "localhost"; //Dns.GetHostName();
    private static int SERVER_PORT = 8000;

    static void Main(string[] args)
    {
        Console.WriteLine("Client: connecting to " + SERVER_ADDR + " server");

        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socket.ReceiveTimeout = 30000;
        socket.ReceiveBufferSize = BUFFER_SIZE;
        IPHostEntry ipHostInfo = Dns.GetHostEntry(SERVER_ADDR);

        IPAddress ipAddress = null;
        for (int k = 0; k < ipHostInfo.AddressList.Length; k++)
            if (ipHostInfo.AddressList[k].AddressFamily == AddressFamily.InterNetwork)
            {
                ipAddress = ipHostInfo.AddressList[k];
                break;
            }

        socket.Connect(new IPEndPoint(ipAddress, SERVER_PORT));
        Console.WriteLine("Client: connected");

        byte[] buffer = new byte[BUFFER_SIZE];
        int total = 0;
        int read = socket.Receive(buffer, buffer.Length, SocketFlags.None);
        total += read;

        Console.WriteLine("Client: read " + read + " bytes. " + total + " total");
        while (read > 0)
        {
            try
            {
                read = socket.Receive(buffer, buffer.Length, SocketFlags.None);
                total += read;

                Console.WriteLine("Client: read " + read + " bytes. " + total + " total: ");
            }
            catch (Exception se)
            {
                Console.WriteLine(se.ToString());
                break;
            }
        }

        Console.WriteLine("Client: received " + total + " bytes");

        socket.Shutdown(SocketShutdown.Both);
        socket.Close();

        Console.WriteLine("Connection Closed.");

        Console.ReadKey();
    }
  }
}

Я скомпилировал это с помощью Visual Studio 2010 и клиентского профиля .NET 4, но я подозреваю, что он не работает в других версиях .NET.

Вот вывод с сервера:

Server: Bound to localhost (127.0.0.1):8000
Server: Started. Awaiting connection.
Server: A Client connected
Server: sending data
Server: Done sending. 7 bytes (Success)
Server: CLient Disconnected

А это вывод клиента

Client: connecting to localhost server
Client: connected
Client: read 0 bytes. 0 total
Client: received 0 bytes
Connection Closed.

Обратите внимание на разницу между тем, что отправлено с сервера, и тем, что получено клиентом. Кроме того, если закомментирована строка, закрывающая сокет на сервере, клиент просто повиснет в ожидании получения данных.

1 Ответ

2 голосов
/ 23 октября 2010

Это кажется маловероятным, но я могу подтвердить эту проблему: я попытался запустить его с включенным Антивирусом Касперского. Но когда я его выключил, он работает нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...