C # сеть TcpClient - PullRequest
       22

C # сеть TcpClient

0 голосов
/ 07 октября 2011

Может кто-нибудь сказать мне, почему "Прошел?" печатается только когда аргумент Thread.Sleep равен <110? </p>

Обновление <7.X.2011 5PM ET>: я думаю, что происходит то, что конец сервера насыщается клиентом Write (a), что затем каким-то образом влияет на возможность отправки данных до закрытия соединения. Может быть, буфер сетевого чтения заполняется?

Всякий раз, когда число итераций становится выше 165хх, "Прошел?" не отправляется, в любое время число итераций <165xx, строка отправляется. Это число достигается во сне 107 и далее. Значение сна, равное 107, иногда отправляет строку в зависимости от других потоков (ОС), работающих в фоновом режиме. </p>

Значение итерации никогда не становится выше 165хх, даже если для Sleep установлено большое значение (скажем, 2 секунды), что заставляет меня считать, что сетевой буфер заполнен.

    static void fClient()
    {
        int iterations = 0;
        TcpClient client = new TcpClient("localhost", 22320);

        BinaryReader br = new BinaryReader(client.GetStream());
        BinaryWriter bw = new BinaryWriter(client.GetStream());
        while (true)
        {
            try
            {
                if (client.Available > 0)
                {
                    Console.WriteLine(br.ReadString());
                }
                else
                {
                    bw.Write("a");
                    iterations++;
                }
            }
            catch (IOException)
            {
                Console.WriteLine("EXCEPTION");
                //exception always reads: Unable to write....
                // (thrown by bw.Write("a"))
                // show iterations count
                break;
            }
        }
    }

    static void Main(string[] args)
    {
        TcpListener server = new TcpListener(22320);
        server.Start();

        new Thread(fClient).Start();
        Thread.Sleep(200);

        TcpClient client = server.AcceptTcpClient();

        BinaryWriter binWrite = new BinaryWriter(client.GetStream());
        binWrite.Write("Went Through?");
        binWrite.Flush();
        client.Close();
    }

Ответы [ 2 ]

0 голосов
/ 08 октября 2011

Мне кажется, я наконец-то понял это.

Две конечные точки A и B разговаривают друг с другом: A <-> B

Когда A отправляет сообщение B и затем закрывает свой TcpClientобъект, я предположил, что свойство TcpClient.Available на B будет по-прежнему перечислять это последнее сообщение от A как полученное, а затем BinaryReader.ReadString () сможет получить это сообщение, даже если соединение TCP / IP было разорвано A.

Я заметил, что это не всегда так, и теперь я думаю, что понимаю, почему.

После того, как A закрывает соединение, если B только читает из сети, то он сможет получить этопоследнее сообщение от A и свойство Available будет отражать присутствие этого сообщения.Но если B выполняет запись в сеть, эта запись мгновенно обнаружит разорванное соединение и провалит любые последующие операции чтения / записи, даже если свойство Available возвращает> 0.

Так что на самом деле я правильно понял свойство Available, но узнал сегодня, что есть исключения, когда свойство не будет работать так, как ожидалось.

Если я ошибаюсь, исправьте меня.Теперь перейдем к изменению моего приложения.

0 голосов
/ 07 октября 2011

Я также думаю, что код прост :) Но этот не использует Sleep для синхронизации потоков.

static Semaphore Go = new Semaphore(0, 1);

static void Server()
{
    TcpListener server = new TcpListener(22320);
    server.Start();
    Go.Release();

    while (true)
    {
        TcpClient client = server.AcceptTcpClient();
        new Thread((x) => ServerTask(x)).Start(client);
    }
}

static void ServerTask(object clnObj)
{
    TcpClient client = clnObj as TcpClient;

    BinaryReader br = new BinaryReader(client.GetStream());
    BinaryWriter bw = new BinaryWriter(client.GetStream());

    string s = "FromServer: " + br.ReadString();
    bw.Write(s);

    client.Close();
}

static void Client(int i)
{

    TcpClient client = new TcpClient();
    client.Connect("localhost", 22320);

    BinaryReader br = new BinaryReader(client.GetStream());
    BinaryWriter bw = new BinaryWriter(client.GetStream());

    bw.Write(i.ToString());
    Console.WriteLine(br.ReadString());

    client.Close();

}

static void Main(string[] args)
{
    Thread t = new Thread(() => Server());
    t.IsBackground = true;
    t.Start();
    Go.WaitOne();

    Console.WriteLine("Server Started....");
    Parallel.For(0, 21, (i) => Client(i));
    Console.WriteLine("Clients Processed");
    Console.ReadLine();
}
...