Socket.Lier et Connecter en utilisant les adresses locales

Pour tester mon serveur/client de l'application, où chaque client est connu par son adresse IP, j'ai créé plusieurs cartes réseau (voir Comment Créer une Carte Réseau Virtuelle .NET?). Les deux 192.168.0.10 et 11 correspondent maintenant aux locaux adaptateurs ethernet (10 étant le "réel", 11 étant une carte de bouclage).

Le client peut Connect lui-même sur le serveur tant qu'il n'a pas Bind son socket à une adresse spécifique. Mais si c'est le cas, le serveur n'a rien remarqué et un délai d'attente se produit dans le client (je veux utiliser Bind que pour des raisons de sécurité, le serveur détecte automatiquement le client se connecte lui-même en regardant l'adresse IP de l'extrémité distante de la nouvelle connexion: le serveur de perte de connexion à la fois si elle ne connaît pas l'adresse IP - auparavant, j'ai été en utilisant plusieurs machines virtuelles, mais il utilise beaucoup plus de RAM et est moins pratique à utiliser).

Voici le code de mon serveur, en écoutant par exemple, sur 192.168.0.10:1234

IPEndPoint myEP = new IPEndPoint(myAddress, myPort);
Socket listeningSocket = new Socket(myAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listeningSocket.Bind(myEP);
listeningSocket.Listen(50);
Socket acceptedSocket = listeningSocket.Accept();

Voici le code de mon client, en liaison par exemple à 192.168.0.11 (un port) et la connexion à 192.168.0.10:1234

Socket socket = new Socket(svrAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(myAddress, 0)); //Bind to local address using automatic port
socket.Connect(new IPEndPoint(svrAddress, svrPort)); //Works fine without Bind, timeout with Bind

J'ai essayé la même chose en utilisant le raccourci adresses IPv6 mais j'obtiens exactement le même résultat.
Si je Bind le client sur la même adresse (en utilisant un autre port que le serveur), il fonctionne très bien.

Une idée de ce que je fais mal?

MODIFIER Voici mon test de projets (il peut être utile à quelqu'un)

Partie serveur:

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace Server
{
class Program
{
static void Main(string[] args)
{
IPAddress[] ips = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
string line = string.Empty;
while (line != "q")
{
//Gets the IP address to listen on.
Console.WriteLine("IP to listen on:");
int count = 0;
foreach (IPAddress ip in ips)
Console.WriteLine("{0}: {1}", ++count, ip.ToString());
string numString = Console.ReadLine();
int pos = Convert.ToInt32(numString) - 1;
IPAddress myAddress = ips[pos]; //Removing or not the scope ID doesn't change anything as "localEndPoint" below will contain it no matter what
//Binds and starts listening.
IPEndPoint myEP = new IPEndPoint(myAddress, 12345);
Socket listeningSocket = new Socket(myAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listeningSocket.Bind(myEP);
listeningSocket.Listen(50);
IPEndPoint localEndPoint = (IPEndPoint)listeningSocket.LocalEndPoint;
Console.WriteLine("Listening on {0}:{1}", localEndPoint.Address, localEndPoint.Port);
Task.Factory.StartNew(() =>
{
try
{
//Accepts new connections and sends some dummy byte array, then closes the socket.
Socket acceptedSocket = listeningSocket.Accept();
IPEndPoint remoteEndPoint = (IPEndPoint)acceptedSocket.RemoteEndPoint;
Console.WriteLine("Accepted connection from {0}:{1}.", remoteEndPoint.Address, remoteEndPoint.Port);
acceptedSocket.Send(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
acceptedSocket.Close(5000);
Console.WriteLine("-= FINISHED =- Type q to quit, anything else to continue");
}
catch (Exception ex)
{ }
});
line = Console.ReadLine();
//Closes the listening socket.
listeningSocket.Close();
}
}
}
}

Partie Client

using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace Client
{
class Program
{
static void Main(string[] args)
{
IPAddress[] ips = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
string line = string.Empty;
while (line != "q")
{
//Gets the IP address to connect to (removes the "scope ID" if it's an IPv6).
Console.WriteLine("IP to connect to:");
int count = 0;
foreach (IPAddress ip in ips)
Console.WriteLine("{0}: {1}", ++count, ip.ToString());
string numString = Console.ReadLine();
int pos = Convert.ToInt32(numString) - 1;
IPAddress svrAddress = ips[pos].AddressFamily == AddressFamily.InterNetworkV6
? new IPAddress(ips[pos].GetAddressBytes())
: ips[pos];
Console.WriteLine("Connecting to " + svrAddress);
//Gets the IP address to bind on (can chose "none" - also removes the "scope ID" if it's an IPv6).
Console.WriteLine("IP to bind to:");
Console.WriteLine("0: none");
count = 0;
IPAddress[] filteredIps = ips.Where(i => i.AddressFamily == svrAddress.AddressFamily).ToArray();
foreach (IPAddress ip in filteredIps)
Console.WriteLine("{0}: {1}", ++count, ip.ToString());
numString = Console.ReadLine();
pos = Convert.ToInt32(numString) - 1;
IPEndPoint localEndPoint = (pos == -1)
? null
: new IPEndPoint(
filteredIps[pos].AddressFamily == AddressFamily.InterNetworkV6
? new IPAddress(filteredIps[pos].GetAddressBytes())
: filteredIps[pos]
, 0);
Console.WriteLine("Binding to " + (localEndPoint == null ? "none" : localEndPoint.Address.ToString()));
//Binds to an address if we chose to.
Socket socket = new Socket(svrAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
if (localEndPoint != null)
socket.Bind(localEndPoint);
Task.Factory.StartNew(() =>
{
try
{
//Connects to the server and receives the dummy byte array, then closes the socket.
socket.Connect(new IPEndPoint(svrAddress, 12345));
IPEndPoint remoteEndPoint = (IPEndPoint)socket.RemoteEndPoint;
Console.WriteLine("Connected to {0}:{1}", remoteEndPoint.Address, remoteEndPoint.Port);
byte[] buffer = new byte[10];
Console.WriteLine((socket.Receive(buffer) == buffer.Length) ? "Received message" : "Incorrect message");
socket.Close();
}
catch (Exception ex)
{
//An exception occured: should be a SocketException due to a timeout if we chose to bind to an address.
Console.WriteLine("ERROR: " + ex.ToString());
}
Console.WriteLine("-= FINISHED =- Type q to quit, anything else to continue");
});
line = Console.ReadLine();
}
}
}
}
Essayez de présenter le plus petit exemple de code qui présente à votre problème. La plupart des utilisateurs ici ne souhaitez déboguer votre long code.
J'ai d'abord ajouté un petit échantillon (5 lignes pour le serveur, 3 pour le client), puis plus tard, j'ai aussi ajouté la source d'un simple projet de test pour les deux (j'ai pensé qu'il pourrait aider quelqu'un que ça fonctionne, mais peut-être qu'il a également fait peur aux gens qui avaient envie de répondre).

OriginalL'auteur user276648 | 2012-07-02