C#中的套接字编程-客户端从不连接到服务器 [英] Socket Programming in C# - The Client Never Connects to the Server

查看:120
本文介绍了C#中的套接字编程-客户端从不连接到服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不是在寻找完整的书面解决方案,我只是想知道出什么问题了,因为这是学校作业的一部分.这两堂课都是由老师写的,所以我认为我的电脑出了点问题,但是我不知道在哪里看.我搜索了其他一些解决方案,但除了低级解决方案外,找不到与该解决方案不同的任何解决方案,但我也从老师那儿得到了一个低级解决方案,这也行不通.

I'm not looking for a complete written solution, I only want to know what is going wrong, as it's part of a school assignment. Both classes are written by the teacher, so I assume something is going wrong on my computer, but I have no idea where to look. I searched for some other solutions and can't find any which is different from this one, except low-level solutions but I also got a low-level solution from my teacher and that also doesn't work.

服务器:

var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ipAddress, clientPort);
server.Start();
TcpClient client = server.AcceptTcpClient(); // The server gets here
StreamReader clientIn = new StreamReader(client.GetStream());
StreamWriter clientOut = new StreamWriter(client.GetStream());
clientOut.AutoFlush = true;
while (true)
{
    string msg = clientIn.ReadLine();
    Console.WriteLine(msg);
    clientOut.WriteLine(msg);  
}

客户:

TcpClient client = new TcpClient("localhost", serverPort); //The client gets here
StreamReader clientIn = new StreamReader(client.GetStream());
StreamWriter clientOut = new StreamWriter(client.GetStream());

clientOut.AutoFlush = true;

while (true)
{
    clientOut.WriteLine(Console.ReadLine());
    Console.WriteLine(clientIn.ReadLine());
}

由于客户端处于try-catch块中(在获得连接之前一直处于循环状态),因此他尝试多次连接到服务器.服务器没有被捕获,因为AcceptTcpClient只是等待连接,但是当它们位于同一ip上且位于另一个进程的端口上时,它们永远不会达到任何连接.

As the client is in a try-catch block, which is in a loop until he has the connection, he tries to connect to the server many times. The server isn't catched, as AcceptTcpClient just waits for a connection, but while they are on the same ip and on the port of the other process, they never reach any connection.

连接是在单独的线程中启动的,但是主线程似乎要等到一个线程完成为止,这不是我所期望的.我试图让他们俩都使用各种方法(使用Thread.Sleep(1000)Thread.Sleep(0)(文档说如果您这样做的话,将安排另一个线程)和while(stopwatch<1000ms) {for(i<100000)}),它们都无济于事.仅当连接线程的睡眠消失并且连接线程再次创建客户端时,主线程才会有所进展.

The connections are started in separate threads, but the main thread seems to wait until one is finished, which is not what I expected. I tried to let them both sleep on various methods (with Thread.Sleep(1000), Thread.Sleep(0) (documentation said that another thread would be scheduled if you'd do that) and while(stopwatch<1000ms) {for(i<100000)}), none of them helped. The main thread only has some progress at the moment that the sleep of the connection-thread is gone and the connection-thread again creates the client.

该问题也出现在另一台W7 64位计算机上.

The problem also arises on another W7 64 bits computer.

有人知道是什么问题吗?

Does anybody know what the problem is?

推荐答案

问题几乎可以肯定存在于您在构建服务器时使用IPAddress.Any的事实.之所以成为问题,是因为这不一定会解决localhost,尽管您可能会很幸运,但并不一致.因此,我建议使用以下IP地址启动服务器:

The problem almost certainly resides in the fact that you're using IPAddress.Any when building the server. The reason that's an issue is because that will not necessarily resolve to localhost, though you may get lucky, it's not consistent. So, I would recommend starting up the server with an IP address like this:

var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ipAddress, clientPort);

接下来,尽管我确信您正在执行此操作,但请确保clientPortserverPort的端口相同.

Next, though I'm confident you're doing this, ensure that the ports are the same for both clientPort and serverPort.

接下来,我非常怀疑while (true)循环,因此在下面的示例中,我将对其进行更改.除非 不可能 始终避免使用while (true),否则您实际上是在寻求问题.

Next, the while (true) loop is very suspect to me so in my example below I'm going to change that. Unless impossible always avoid while (true), you are literally begging for a problem.

最后,围绕在这里如何进行线程化,您将需要以某种方式构建两个单独的线程,而我将推荐BackgroundWorker类(其他人可能会推荐async-await,但我不知道对此还不够,建议您将需要使用.NET 4.5,但我不知道您是否使用).

Finally, surrounding how you will do threading here, you're going to need to build two separate threads somehow and I'm going to recommend the BackgroundWorker class (others may recommend async-await but I don't know enough about it yet to recommend that and you would need to be using .NET 4.5 and I don't know if you are).

因此,您可以为服务器构建一个这样的BackgroundWorker(也可以为客户端构建另一个类似的东西):

So, you could build a BackgroundWorker like this for the server (and you can build another one similar for the client):

var worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;

worker.ProgressChanged += (s, args) =>
{
    Console.WriteLine(args.UserState);
}

worker.DoWork += (s, args) =>
{
    // startup the server on localhost
    var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
    TcpListener server = new TcpListener(ipAddress, clientPort);
    server.Start();

    while (!worker.CancellationPending)
    {
        // as long as we're not pending a cancellation, let's keep accepting requests
        TcpClient client = server.AcceptTcpClient();

        StreamReader clientIn = new StreamReader(client.GetStream());
        StreamWriter clientOut = new StreamWriter(client.GetStream());
        clientOut.AutoFlush = true;

        while ((string msg = clientIn.ReadLine()) != null)
        {
            worker.ReportProgress(1, msg);  // this will fire the ProgressChanged event
            clientOut.WriteLine(msg);
        }
    }
}

最后,您需要在某个地方通过调用RunWorkerAsync来启动这些工作程序,如下所示:

Finally, somewhere you'll need to startup these workers by calling RunWorkerAsync like this:

worker.RunWorkerAsync();

更新

好的,下面是一个可以正常运行的2104控制台应用程序.您需要注意的一件事是,使用var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];时,我们得到的IP地址看起来像::1一样,这就是问题所在.但是,如果我们监听127.0.0.1:2104,则客户端能够连接,因为发出var result = client.BeginConnect("localhost", 2104, null, null);时客户端试图连接的对象,这与发出new TcpClient("localhost", 2104);相同.

Update

Alright, below is a fully working console application connecting on 2104. One thing that you need to note is that when using var ipAddress = Dns.GetHostEntry("localhost").AddressList[0]; we are getting an IP address that looks like this ::1 and that is the problem. However, if we listen on 127.0.0.1:2104 the client is able to connect because that what it's trying to connect to when issuing var result = client.BeginConnect("localhost", 2104, null, null);, which would be the same as issuing new TcpClient("localhost", 2104);.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net.Sockets;
using System.ComponentModel;
using System.Threading;
using System.Net;

namespace ConsoleApplication13
{
    class Program
    {
        static void Main()
        {
            var worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.WorkerSupportsCancellation = true;

            worker.ProgressChanged += (s, args) =>
            {
                Console.WriteLine(args.UserState);
            };

            worker.DoWork += (s, args) =>
            {
                // startup the server on localhost 
                var ipAddress = IPAddress.Parse("127.0.0.1");
                TcpListener server = new TcpListener(ipAddress, 2104);
                server.Start();

                while (!worker.CancellationPending)
                {
                    Console.WriteLine("The server is waiting on {0}:2104...", ipAddress.ToString());

                    // as long as we're not pending a cancellation, let's keep accepting requests 
                    TcpClient attachedClient = server.AcceptTcpClient();

                    StreamReader clientIn = new StreamReader(attachedClient.GetStream());
                    StreamWriter clientOut = new StreamWriter(attachedClient.GetStream());
                    clientOut.AutoFlush = true;

                    string msg;
                    while ((msg = clientIn.ReadLine()) != null)
                    {
                        Console.WriteLine("The server received: {0}", msg);
                        clientOut.WriteLine(string.Format("The server replied with: {0}", msg));
                    }
                }
            };

            worker.RunWorkerAsync();

            Console.WriteLine("Attempting to establish a connection to the server...");

            TcpClient client = new TcpClient();

            for (int i = 0; i < 3; i++)
            {
                var result = client.BeginConnect("localhost", 2104, null, null);

                // give the client 5 seconds to connect
                result.AsyncWaitHandle.WaitOne(5000);

                if (!client.Connected)
                {
                    try { client.EndConnect(result); }
                    catch (SocketException) { }

                    string message = "There was an error connecting to the server ... {0}";

                    if (i == 2) { Console.WriteLine(message, "aborting"); }
                    else { Console.WriteLine(message, "retrying"); }

                    continue;
                }

                break;
            }

            if (client.Connected)
            {
                Console.WriteLine("The client is connected to the server...");

                StreamReader clientIn = new StreamReader(client.GetStream());
                StreamWriter clientOut = new StreamWriter(client.GetStream());

                clientOut.AutoFlush = true;

                string key;
                while ((key = Console.ReadLine()) != string.Empty)
                {
                    clientOut.WriteLine(key);
                    Console.WriteLine(clientIn.ReadLine());
                }
            }
            else { Console.ReadKey(); }
        }
    }
}

这篇关于C#中的套接字编程-客户端从不连接到服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆