无法连接到另一台计算机上的TCPClient

时间:2016-08-18 22:07:03

标签: c# tcpclient tcplistener

所以我有两台笔记本电脑连接到同一个wifi网络,一台运行一个非常简单的服务器,另一台是连接它的非常简单的客户端。当我在一台笔记本电脑上同时运行服务器和客户端时,它们连接没有问题,但是当在每台笔记本电脑上运行时,客户端无法连接到服务器。

服务器的代码是:

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

namespace Utils
{
    /// <summary>
    /// A base server which handles listening for client connections and has simple API to communicate back and forth
    /// </summary>
    public class BaseServer
    {
        #region Properties and Fields

        /// <summary>
        /// The listener we can use to detect incoming connections from clients to the server
        /// </summary>
        private TcpListener Listener { get; set; }

        /// <summary>
        /// Our interface to the single client we are supporting for now
        /// </summary>
        public Comms ClientComms { get; private set; }

        /// <summary>
        /// Determines whether we have clients connected
        /// </summary>
        public bool Connections { get; private set; }

        #endregion

        public BaseServer()
        {
            Listener = new TcpListener(IPAddress.Any, 1490);
            Listener.Start();

            ListenForNewClient();
        }

        /// <summary>
        /// Starts an asynchronous check for new connections
        /// </summary>
        private void ListenForNewClient()
        {
            Listener.BeginAcceptTcpClient(AcceptClient, null);
        }

        /// <summary>
        /// Callback for when a new client connects to the server
        /// </summary>
        /// <param name="asyncResult"></param>
        protected virtual void AcceptClient(IAsyncResult asyncResult)
        {
            ClientComms = new Comms(Listener.EndAcceptTcpClient(asyncResult));
            ClientComms.OnDataReceived += ProcessMessage;

            ListenForNewClient();
        }

        #region Message Callbacks

        /// <summary>
        /// A function which is called when the Client sends a message to the server.
        /// Override to perform custom message handling
        /// </summary>
        /// <param name="data"></param>
        protected virtual void ProcessMessage(byte[] data) { }

        #endregion

    }
}

客户端的代码是:

using System;
using System.Net.Sockets;

namespace Utils
{
    /// <summary>
    /// A base client class which connects and communicates with a remote server
    /// </summary>
    public class BaseClient
    {
        #region Properties and Fields

        /// <summary>
        /// The interface to the server
        /// </summary>
        public Comms ServerComms { get; private set; }

        #endregion

        public BaseClient(string ipAddress, int portNumber = 1490)
        {
            // Attempt to connect
            try
            {
                ServerComms = new Comms(new TcpClient(ipAddress, portNumber));
                ServerComms.OnDataReceived += OnMessageReceived;
                ServerComms.OnDisconnect += OnServerDisconnect;
            }
            catch (Exception e)
            {
                Console.WriteLine("Connection failed");
            }
        }

        #region Callbacks

        /// <summary>
        /// A function which is called when this client receives a message.
        /// Override to perform behaviour when custom messages arrive.
        /// </summary>
        /// <param name="data"></param>
        protected virtual void OnMessageReceived(byte[] data) { }

        /// <summary>
        /// A function called when this client can no longer communicate to the server it is connected to
        /// </summary>
        protected virtual void OnServerDisconnect() { }

        #endregion
    }
}

服务器从主循环启动,如下所示:

using System;

namespace BuildServer
{
    class Program
    {
        static void Main(string[] args)
        {
            BaseServer server = new BaseServer();
            while (true)
            {

            }
        }
    }
}

并且客户端就像这样启动:

using System;
using Utils;

namespace BuildServerClient
{
    class Program
    {
        static void Main(string[] args)
        {
            BaseClient client = new BaseClient();

            while (true)
            {
                Console.WriteLine("Ready");
                string message = Console.ReadLine();
                client.ServerComms.Send(message);
            }
        }
    }
}

最后一个类是一个Comms类,它实际上是TCPClient的包装器,当前并没有真正使用,但我是为了完整性而添加它。

using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using static Utils.Delegates;

namespace Utils
{
    /// <summary>
    /// An interface to a client.
    /// Hides the nuts and bolts and provides a public interface of just data input and output from a data sender/receiver.
    /// </summary>
    public class Comms
    {
        #region Properties and Fields

        private TcpClient Client { get; set; }
        private MemoryStream ReadStream { get; set; }
        private MemoryStream WriteStream { get; set; }
        private BinaryReader Reader { get; set; }
        private BinaryWriter Writer { get; set; }

        /// <summary>
        /// Useful buffer for reading packeted messages from the server
        /// </summary>
        private byte[] ReadBuffer { get; set; }

        /// <summary>
        /// An event that is fired when this Comms receives a message
        /// </summary>
        public event OnDataReceived OnDataReceived;

        /// <summary>
        /// An event that is fired when this Comms can no longer communicate with the client sending it messages
        /// </summary>
        public event OnDisconnect OnDisconnect;

        #endregion

        public Comms(TcpClient client)
        {
            Client = client;
            ReadStream = new MemoryStream();
            WriteStream = new MemoryStream();
            Reader = new BinaryReader(ReadStream);
            Writer = new BinaryWriter(WriteStream);

            ReadBuffer = new byte[2048];
            Client.NoDelay = true;

            StartListening();
        }

        #region Data Sending Functions

        /// <summary>
        /// Convert a string to a byte array and then send to our client
        /// </summary>
        /// <param name="client"></param>
        /// <param name="str"></param>
        public void Send(string str)
        {
            SendByteArray(Encoding.UTF8.GetBytes(str));
        }

        /// <summary>
        /// Send a byte array to our client
        /// </summary>
        /// <param name="client"></param>
        /// <param name="bytes"></param>
        protected void SendByteArray(byte[] bytes)
        {
            Writer.Write(bytes);

            int bytesWritten = (int)WriteStream.Position;
            byte[] result = new byte[bytesWritten];

            WriteStream.Position = 0;
            WriteStream.Read(result, 0, bytesWritten);
            WriteStream.Position = 0;

            Client.GetStream().BeginWrite(result, 0, result.Length, null, null);
            Writer.Flush();
        }

        #endregion

        #region Data Receiving Functions

        /// <summary>
        /// Start listening for messages from the server
        /// </summary>
        private void StartListening()
        {
            try
            {
                Client.GetStream().BeginRead(ReadBuffer, 0, 2048, StreamReceived, null);
            }
            catch
            {
                OnDisconnect?.Invoke();
            }
        }

        /// <summary>
        /// Callback which processes a message sent from the server
        /// </summary>
        /// <param name="ar"></param>
        private void StreamReceived(IAsyncResult ar)
        {
            int bytesRead = 0;
            try
            {
                lock (Client.GetStream())
                {
                    bytesRead = Client.GetStream().EndRead(ar);
                }
            }
            catch { }

            //Create the byte array with the number of bytes read
            byte[] data = new byte[bytesRead];

            //Populate the array
            for (int i = 0; i < bytesRead; i++)
            {
                data[i] = ReadBuffer[i];
            }

            OnDataReceived?.Invoke(data);

            //Listen for new data
            StartListening();
        }

        #endregion
    }
}

IP地址和端口号是正确的,因为它在同一台机器上运行时有效,我以为它可能是防火墙问题或其他什么?有没有人对可能导致这个问题的原因有任何想法?

2 个答案:

答案 0 :(得分:3)

确保服务器计算机上的防火墙(Windows防火墙或其他任何地方)已关闭,或者您的端口号有防火墙例外。

答案 1 :(得分:0)

大卫的回答是正确的。我之前尝试过只为私有网络禁用防火墙。但是,我为访客和公共网络禁用了防火墙,它起了作用。

codenoir提出的测试方法在排除我的客户方面也非常有效。我怀疑它与防火墙有关,但是一旦你排除了不可能的......

感谢两者