Итак, у меня есть два ноутбука, подключенных к одной сети Wi-Fi, причем один работает с очень простым сервером, а другой - очень простой клиент, подключающийся к нему. Когда я запускаю как сервер, так и клиент на одном ноутбуке, они подключаются без проблем, но при запуске одного на каждом ноутбуке клиент не может подключиться к серверу.Невозможно подключиться к TCPClient на другом компьютере
Код для сервера заключается в следующем:
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-адреса и номера портов являются правильными и, так как он работает, когда работает на той же машине, я думал, что это может быть проблемой брандмауэра или что-то? Есть ли у кого-нибудь идеи относительно того, что может вызвать эту проблему?
Что идет не так точно? –
Не подключается и время. В разделе, где я создаю TCPClient &, вы пытаетесь поймать попытку, и он всегда выдает исключение из-за таймаута. –