Я делаю простое приложение для чата, используя TcpClient и TcpServer из System.Net.
У меня на ПК все работает, сервер общается с клиентом и наоборот. Но когда я пытаюсь подключиться к тому же серверу, используя другой компьютер (даже в той же подсети, что и мой компьютер), это не работает.
Я пробовал переадресацию портов через свой маршрутизатор, брандмауэр и все равно ничего.
Вы видите мой сайт сообщает, что в соединении отказано. Хотя!! Иногда говорится, что соединение полностью истекло.
Я не уверен, что не так с моим кодом или моим компьютером, я был бы очень признателен за помощь от людей, которые более опытны в этой области, чем я.
Вот конфигурация переадресации портов в моем маршрутизаторе:

Если вам нужен код для клиента и сервера, вот они:
P.S. Я вношу изменения в клиент в части BeginConnect() внизу, чтобы изменить IP-адрес, к которому я подключаюсь.
Клиент:
using System;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
namespace TcpTest_Client_
{
public partial class Form1 : Form
{
TcpClient client;
IPAddress localIP = null;
bool connected = false;
public Form1()
{
InitializeComponent();
}
public void clientConnectCallback(IAsyncResult result)
{
try
{
client.EndConnect(result);
Log("Connected to " + client.Client.RemoteEndPoint);
connected = true;
NetworkStream clientStream = client.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch (Exception ex)
{
//a socket error has occured
Log(ex.Message);
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
Log("Server on has disconnected");
break;
}
//message has successfully been received
UTF8Encoding encoder = new UTF8Encoding();
string bufferincmessage = encoder.GetString(message, 0, bytesRead);
Log("Server: " + bufferincmessage);
}
}
catch (Exception ex)
{
Log(ex.Message);
}
}
public void Log(string msg)
{
richTextBox1.BeginInvoke(new Action(
() =>
{
richTextBox1.Text += msg + "\n";
}));
}
private void Form1_Load(object sender, EventArgs e)
{
foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
{
if (addr.AddressFamily == AddressFamily.InterNetwork)
{
localIP = addr;
break;
}
}
client = new TcpClient(AddressFamily.InterNetwork);
}
private void button2_Click(object sender, EventArgs e)
{
try
{
client.BeginConnect(IPAddress.Parse("109.252.107.144"), 1234, clientConnectCallback, client);
}
catch (Exception ex)
{
Log(ex.Message);
}
}
private void button1_Click(object sender, EventArgs e)
{
if (connected)
{
UTF8Encoding encoder = new UTF8Encoding();
NetworkStream clientStream = client.GetStream();
byte[] stringToSend = new byte[richTextBox2.Text.Length];
stringToSend = encoder.GetBytes(richTextBox2.Text);
clientStream.Write(stringToSend, 0, stringToSend.Length);
}
}
}
}
Сервер:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace TcpTest
{
public partial class Form1 : Form
{
private TcpListener server;
private List<Thread> clientThreads = null;
public Thread MainThread;
public Form1()
{
InitializeComponent();
}
public void Log(string msg)
{
richTextBox1.BeginInvoke(new Action(
() =>
{
richTextBox1.Text += msg + "\n";
}));
}
public static string bufferincmessage;
public void AcceptSocketPackets(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch (Exception ex)
{
//a socket error has occured
Log(ex.Message);
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
Log("Client on " + tcpClient.Client.RemoteEndPoint + " has disconnected from the server");
break;
}
//message has successfully been received
UTF8Encoding encoder = new UTF8Encoding();
bufferincmessage = encoder.GetString(message, 0, bytesRead);
Log("Client from " + tcpClient.Client.RemoteEndPoint + ": " + bufferincmessage);
string stringToSend = "You sent me: " + bufferincmessage;
byte[] messageToSend = new byte[stringToSend.Length];
messageToSend = encoder.GetBytes(stringToSend);
clientStream.Write(messageToSend, 0, messageToSend.Length);
}
}
public void SocketAcceptCallback(IAsyncResult result)
{
TcpClient newClient = server.EndAcceptTcpClient(result);
Log("Accepted client on " + newClient.Client.RemoteEndPoint);
clientThreads.Add(new Thread(new ParameterizedThreadStart(AcceptSocketPackets)));
clientThreads[clientThreads.Count - 1].Start(newClient);
server.BeginAcceptTcpClient(SocketAcceptCallback, server);
}
private void Form1_Load(object sender, EventArgs e)
{
MainThread = Thread.CurrentThread;
clientThreads = new List<Thread>();
try
{
IPAddress localIP = null;
foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
{
if (addr.AddressFamily == AddressFamily.InterNetwork)
{
localIP = addr;
break;
}
}
localIP = IPAddress.Any;
// could also use this:
// server = new TcpListener(new IPEndPoint(IPAddress.Any, 1234));
server = new TcpListener(new IPEndPoint(localIP, 1234));
Log("Starting server on " + localIP + ":1234");
server.Start(6);
server.BeginAcceptTcpClient(SocketAcceptCallback, server);
Log("Started server on " + localIP + ":1234");
}
catch (Exception ex)
{
Log(ex.Message);
}
}
}
}
@RichardHubley, я добавил два правила (входящий, исходящий) для порта, который использую. И фактически отключил его.
Возможно, другое приложение использует порт 1234. Я стараюсь не использовать номера портов, которые используют другие люди. Лучше всего использовать cmd.exe> Netstat -a, чтобы убедиться, что соединения работают правильно. Также используйте cmd.exe> Ping IP или Имя компьютера. Попробуйте указать IP-адрес и имя компьютера, так как одно может работать, а другое - нет. Сообщите мне результаты и помогу в дальнейшем.
Спасибо, @jdweng, я проверил соединения через> Netstat -a. Я видел единственное приложение, работающее на этом порту, которое было моим. Кроме того, я пробовал пинговать себя с разными IP-адресами: 127.0.0.1 (localhost), 192.168.1.11, мой внешний IP-адрес, мое имя компьютера - все работало как шарм, без потери пакетов, ничего.
Попробуйте выполнить обратное с серверного ПК обратно на ваш клиент. Иногда пинг работает в одном направлении, а не в другом. Если порт заблокирован на сервере, эхо-запрос может по-прежнему работать, так как PING реализован в карте Ethernet, а не заблокирован.
@jdweng, просто попробовал пинговать один из моих компьютеров друзей, все работало, они получили пакеты, но не наоборот, они не могли пинговать меня по какой-то причине ... у них истекло время ожидания ..
Кстати, забыл упомянуть, я считаю, что это не очень важно и не связано, но я изменил некоторые вещи в параметрах адаптера Ethernet в Windows. Я установил статический внутренний IP-адрес, настроив его вручную так: pp.userapi.com/c848624/v848624989/654b7/R0bWskeDPBk.jpg
они получили * я думаю *
Если вы используете один и тот же маршрутизатор, не используйте внешний IP-адрес. Используйте внутренний IP «сервера». Я не думаю, что вы можете отправить сообщение со своего маршрутизатора и получить его обратно от вашего интернет-провайдера.
Смена IP-адреса может занять от 45 минут до часа, прежде чем сервер распознает IP-адрес. Перезагрузка ПК ускорит время. ПК ARP свой IP-адрес при включении или обычно каждые полчаса. Вы пробовали пинговать в обратном направлении, используя как IP-адрес, так и имя компьютера? Номер порта может быть заблокирован на удаленном компьютере или неправильная маска IP-адреса на сервере. В прошлом я отлаживал многие из этих проблем. Знайте все проблемы и способы их устранения.
Ваш интернет-провайдер не может рекламировать свой IP-адрес в сети. Я хотел бы пинговать твоего друга. Затем попросите его проверить свою таблицу ARP с помощью cmd.exe> ARP -a. Он должен увидеть ваш IP-адрес в таблице. Тогда он сможет ответить вам по тому же IP-адресу. Как только эхо-запрос работает в одном направлении, все маршрутизаторы получают ваш IP-адрес и должны иметь возможность возвращаться через одни и те же маршрутизаторы в течение до 1/2 часа (время, когда таблица ARP удаляет записи).
Спасибо за помощь, @jdweng. Я попробую эти методы, как только приду домой, и отвечу.





С ++ доставляет мне подобные проблемы. Попробуйте создать другой проект, вставьте код сервера и соберите его как Release x86. Если вы измените цель сборки и наша проблема останется прежней, брандмауэр Windows, даже когда он выключен, не позволит серверу или клиенту работать без каких-либо исключений. Если это не сработает, я могу не знать ответа.
Как C++ связан с C#?
Это должно быть проблема с окнами. Со мной так и было. Это могло быть так и для него. Так как я не смог найти в Интернете ответа на свою проблему и потратил часы на ее решение, я решил помочь кому-то, у кого есть такая же проблема, как моя, и просто предложил сделать это. Это может не сработать, но это гипотеза опровергнута
Брандмауэр Windows?