所以我有两台笔记本电脑连接到同一个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地址和端口号是正确的,因为它在同一台机器上运行时有效,我以为它可能是防火墙问题或其他什么?有没有人对可能导致这个问题的原因有任何想法?
答案 0 :(得分:3)
确保服务器计算机上的防火墙(Windows防火墙或其他任何地方)已关闭,或者您的端口号有防火墙例外。
答案 1 :(得分:0)
codenoir提出的测试方法在排除我的客户方面也非常有效。我怀疑它与防火墙有关,但是一旦你排除了不可能的......
感谢两者