无法 read/write 数据 (TcpClient/Server)
Can't read/write data (TcpClient/Server)
我实际上能够将我的 TcpClient 连接到我的 TcpServer,但我无法让它们通信。我尝试了 client.GetStream()
和 BinaryReader/Writer
.
这是我的代码:
-客户端:
public partial class Client : Window
{
#region Constructeurs
public Client() : this(string.Empty, 12221) { }
public Client(string ipDefaut, int portDefaut)
{
InitializeComponent();
numIp.FromString("192.168.2.168");
numPort.Value = portDefaut;
Serveur serveur = new Serveur();
serveur.Show();
}
#endregion
public void Start()
{
if (Ip == null)
return;
if (client == null || client.Client == null)
client = new TcpClient();
if (client.Connected == true)
{
ShowMessage("Déjà connecté.");
return;
}
client = new TcpClient();
try
{
client.ConnectAsync(Ip, Port).Wait(10);
}
catch (SocketException) { }
}
public void Stop()
{
if (client != null && client.Client != null)
if (client.Connected)
{
client.Client.Shutdown(SocketShutdown.Both);
client.Close();
}
}
public string Read()
{
if (client != null && client.GetStream() != null)
if (client.Connected && client.GetStream().DataAvailable)
{
BinaryReader reader = new BinaryReader(client.GetStream());
return reader.ReadString();
}
return string.Empty;
}
public void Send(string info)
{
if (client != null && client.GetStream() != null)
if (client.Connected)
{
BinaryWriter writer = new BinaryWriter(client.GetStream());
writer.Write(info);
writer.Flush();
}
}
private void ShowMessage(string message)
{
labelInfo.Content = message;
Storyboard sb = Resources["sbLabelInfo"] as Storyboard;
sb.Begin(labelInfo);
}
private void Connecter(object sender, RoutedEventArgs e)
{
foreach (string num in numIp.ToStringArray())
if (num == string.Empty)
{
ShowMessage("L'adresse ip doit être complète.");
return;
}
Start();
if (client.Connected)
{
ShowMessage("Connecté");
boutonConnecter.IsEnabled = false;
numIp.IsEnabled = false;
numPort.IsEnabled = false;
boutonAnnuler.Content = "Déconnecter";
}
else
ShowMessage("Impossible de se connecter.");
}
private void Annuler(object sender, RoutedEventArgs e)
{
if ((string)boutonAnnuler.Content == "Annuler")
Close();
else if ((string)boutonAnnuler.Content == "Déconnecter")
{
Stop();
boutonConnecter.IsEnabled = true;
numIp.IsEnabled = true;
numPort.IsEnabled = true;
boutonAnnuler.Content = "Annuler";
}
}
#region Propriétés
public string Ip { get { return numIp.ToString(); } }
public int Port { get { return (int)numPort.Value; } }
#endregion
#region Membres
private TcpClient client = new TcpClient();
#endregion
}
-服务器:
public partial class Serveur : Window
{
#region Constructeurs
public Serveur() : this(12221) { }
public Serveur(int numPortDefaut)
{
InitializeComponent();
foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
if (addr.AddressFamily == AddressFamily.InterNetwork)
numIp.FromString(addr.ToString());
numPort.Value = numPortDefaut;
serveur = new TcpListener(IPAddress.Parse(Ip), Port);
thread = new Thread(Accept);
serveur.Stop();
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
boutonDemarrer.IsEnabled = false;
MessageBox.Show(this, "Connection impossible - Tic Tac Toe", "Impossible de se connecter à internet. Vérifiez votre connection et réessayez.", MessageBoxButton.OK, MessageBoxImage.Warning);
Close();
}
}
#endregion
public void Start()
{
if (serveur != null)
{
try
{
serveur.Start();
}
catch (SocketException) { }
IsConnected = false;
StartThread();
}
else
{
serveur = new TcpListener(IPAddress.Parse(Ip), Port);
Start();
}
}
public void Stop()
{
if (serveur != null)
{
IsConnected = false;
serveur.Stop();
StopThread();
}
}
public void StartThread()
{
if (thread.ThreadState == ThreadState.Stopped)
thread.Start();
}
public void StopThread()
{
if (!IsConnected)
{
IsConnected = true;
while (thread.IsAlive) { }
IsConnected = false;
}
}
private void Accept()
{
while (!IsConnected && serveur != null)
if (serveur.Pending())
{
client = serveur.AcceptTcpClient();
IsConnected = true;
}
}
public string Read()
{
if (client != null && client.GetStream() != null)
if (client.Connected && client.GetStream().DataAvailable)
{
BinaryReader reader = new BinaryReader(client.GetStream());
return reader.ReadString();
}
return string.Empty;
}
public void Send(string info)
{
if (client != null && client.GetStream() != null)
if (client.Connected)
{
BinaryWriter writer = new BinaryWriter(client.GetStream());
writer.Write(info);
writer.Flush();
}
}
private void Demarrer(object sender, RoutedEventArgs e)
{
Start();
boutonAnnuler.Content = "Stop";
boutonDemarrer.IsEnabled = false;
numPort.IsEnabled = false;
numIp.IsEnabled = false;
}
private void Annuler(object sender, RoutedEventArgs e)
{
if ((string)boutonAnnuler.Content == "Annuler")
{
Stop();
Close();
}
else if ((string)boutonAnnuler.Content == "Stop")
{
StopThread();
boutonAnnuler.Content = "Annuler";
boutonDemarrer.IsEnabled = true;
numPort.IsEnabled = true;
numIp.IsEnabled = true;
}
}
#region Propriétés
public string Ip { get { return numIp.ToString(); } }
public int Port { get { return (int)numPort.Value; } }
public bool IsConnected { get; private set; }
#endregion
#region Membres
private TcpListener serveur = null;
private TcpClient client = null;
private Thread thread = null;
#endregion
}
问题是,在调试模式下,client.GetStream().DataAvailable
return 总是 false
。
为什么 return 会这样,我该如何解决?
(numIp
和numPort
是用户需要填写的部分字段)
试试这个:
//tcp server
public class Server
{
private string ip { get; set; }
private int port { get; set; }
private Socket server { get; set; }
public List<ClientInfo> listClientsConnected { get; private set; }
// delegate for events
public delegate void Client_Connected(ClientInfo c);
public delegate void Client_Message(string msg, ClientInfo c);
public Server(string ip, int port)
{
this.ip = ip;
this.port = port;
this.listClientsConnected = new List<ClientInfo>();
}
// start server
public void Start()
{
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse(this.ip), this.port));
server.Listen(1);
server.BeginAccept(new AsyncCallback(ClientConnected), server);
}
// accept client connection
private void ClientConnected(IAsyncResult res)
{
Socket s = (Socket)res.AsyncState;
Socket client = s.EndAccept(res);
ClientInfo clientInf = new ClientInfo()
{
currentClient = client
};
client.BeginReceive(clientInf.buffer, 0, ClientInfo.BUFFER_SIZE_FOR_MESSAGE, 0, new AsyncCallback(ReceiveMessage), clientInf);
// add client to list
listClientsConnected.Add(clientInf);
if (Cliente_Conneted_Event != null)
Cliente_Conneted_Event(clientInf);
}
// receive message from client
private void ReceiveMessage(IAsyncResult ar)
{
ClientInfo cl = (ClientInfo)ar.AsyncState;
Socket s = cl.currentClient;
int read = s.EndReceive(ar);
string msg = null;
if (read > 0)
{
msg = Encoding.ASCII.GetString(cl.buffer, 0, read);
s.BeginReceive(cl.buffer, 0, ClientInfo.BUFFER_SIZE_FOR_MESSAGE, 0, new AsyncCallback(ReceiveMessage), cl);
}
if (Cliente_Message_Event != null)
Cliente_Message_Event(msg, cl);
}
// send message to client
public void sendMessage(string msg, ClientInfo client)
{
if (client.currentClient != null)
{
if (client.currentClient.Connected && !string.IsNullOrEmpty(msg))
{
client.currentClient.Send(Encoding.ASCII.GetBytes(msg));
}
}
}
//events
public event Client_Connected Cliente_Conneted_Event;
public event Client_Message Cliente_Message_Event;
}
// tcp client
public class Client
{
private Socket client { get; set; }
private string clientName { get; set; }
private string ip { get; set; }
private int port { get; set; }
// delegates
public delegate void Client_Connected(ClientInfo c);
public delegate void Client_Message(string msg, ClientInfo c);
public Client(string ip, int port)
{
this.ip = ip;
this.port = port;
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
// connect client to server
public void Connect()
{
ClientInfo clientInf = new ClientInfo()
{
currentClient = client,
};
client.BeginConnect(new IPEndPoint(IPAddress.Parse(this.ip), this.port), new AsyncCallback(ClientConnected), clientInf);
}
// accept client connection
private void ClientConnected(IAsyncResult res)
{
ClientInfo clientInf = (ClientInfo)res.AsyncState;
clientInf.currentClient.BeginReceive(clientInf.buffer, 0, ClientInfo.BUFFER_SIZE_FOR_MESSAGE, 0, new AsyncCallback(ReceiveMessage), clientInf);
// client connected
if (Cliente_Conneted_Event != null)
Cliente_Conneted_Event(clientInf);
}
// receive message from client
private void ReceiveMessage(IAsyncResult ar)
{
ClientInfo cl = (ClientInfo)ar.AsyncState;
Socket s = cl.currentClient;
int read = s.EndReceive(ar);
string msg = null;
if (read > 0)
{
msg = Encoding.ASCII.GetString(cl.buffer, 0, read);
s.BeginReceive(cl.buffer, 0, ClientInfo.BUFFER_SIZE_FOR_MESSAGE, 0, new AsyncCallback(ReceiveMessage), cl);
}
if (Cliente_Message_Event != null)
Cliente_Message_Event(msg, cl);
}
// send message to client
public void sendMessage(string msg, ClientInfo client)
{
if (client.currentClient != null)
{
if (client.currentClient.Connected && !string.IsNullOrEmpty(msg))
{
client.currentClient.Send(Encoding.ASCII.GetBytes(msg));
}
}
}
public event Client_Connected Cliente_Conneted_Event;
public event Client_Message Cliente_Message_Event;
}
// in my case i used a console application
class Program
{
private static Server server;
static void Main(string[] args)
{
string ip = "127.0.0.1";
int port = 3122;
server = new Server(ip, port);
server.Cliente_Conneted_Event += server_Cliente_Conneted_Event;
server.Start();
// connect client 1
Client client = new Client(ip, port);
client.Connect();
client.Cliente_Message_Event+=client_Cliente_Message_Event;
sendMessageToClient();
Console.ReadKey();
}
//receive message from server
private static void client_Cliente_Message_Event(string msg, ClientInfo c)
{
try {
Console.WriteLine("Msg from Server:"+msg);
}
catch(Exception ex){
Console.WriteLine(ex.Message);
}
}
// client connected to server
private static void server_Cliente_Conneted_Event(ClientInfo c)
{
Console.WriteLine("Client Connected...");
}
// send message to all clients from server
private static void sendMessageToClient()
{
try
{
Console.Write("Msg:");
string msg = Console.ReadLine();
// send message to clients
if (server.listClientsConnected.Count > 0)
{
foreach (ClientInfo client in server.listClientsConnected)
server.sendMessage(msg, client);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
sendMessageToClient();
}
}
}
比预期的要长...我终于放弃 TcpClient/Server 使用自己的套接字。
这是结果(我在我的代码中做了一个抽象 class 因为这些 class 是相似的):
摘要class:
public abstract partial class Connectable : Window
{
public abstract void Start();
public abstract void Stop();
public void WaitMessage()
{
WaitMessage(new StateObject() { socket = socket });
}
private void WaitMessage(StateObject so)
{
Socket s = so.socket;
int read = s.Receive(so.buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None);
so.sb.Append(Encoding.UTF8.GetString(so.buffer, 0, read));
if (s.Available > 0)
WaitMessage(so);
else if (NewMessage != null)
{
NewMessage(so.sb.ToString());
so.sb.Clear();
}
}
public void ReceiveMessage()
{
StateObject state = new StateObject() { socket = socket };
try { socket.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(MessageReceived), state); }
catch (SocketException e) { Console.WriteLine(e.Message); }
}
protected void MessageReceived(IAsyncResult ar)
{
StateObject so = (StateObject)ar.AsyncState;
Socket s = so.socket;
int read = s.EndReceive(ar);
so.sb.Append(Encoding.UTF8.GetString(so.buffer, 0, read));
if (s.Available > 0)
s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(MessageReceived), so);
else if (NewMessage != null)
{
NewMessage(so.sb.ToString());
so.sb.Clear();
}
}
public void SendMessage(string msg)
{
if (socket != null)
{
if (socket.Connected && !string.IsNullOrEmpty(msg))
{
socket.Send(Encoding.UTF8.GetBytes(msg));
}
}
}
protected void ShowMessage(string message)
{
Console.WriteLine(message);
}
public virtual bool IsConnected()
{
if (socket == null)
return false;
return socket.Connected;
}
#region Members
protected Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public Message NewMessage;
#endregion
#region Delegates
public delegate void Message(string message);
#endregion
}
服务器class:
public partial class Server : Connectable
{
#region Constructeurs
public Server() : this(12221) { }
public Server(int numPortDefaut)
{
InitializeComponent();
socket = null;
NewMessage += ShowMessage;
foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
if (addr.AddressFamily == AddressFamily.InterNetwork)
numIp.FromString(addr.ToString());
numPort.Value = numPortDefaut;
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
boutonDemarrer.IsEnabled = false;
MessageBox.Show(this, "Connection impossible - Tic Tac Toe", "Impossible de se connecter à internet. Vérifiez votre connection et réessayez.", MessageBoxButton.OK, MessageBoxImage.Warning);
Close();
}
}
#endregion
public override void Start()
{
if (socketListener.IsBound)
{
if (socket != null)
{
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(false);
socket.Dispose();
socket = null;
}
socketListener.Close();
socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
try
{
socketListener.Bind(new IPEndPoint(IPAddress.Parse(Ip), Port));
socketListener.Listen(1);
AcceptConnection();
}
catch (SocketException e) { Console.WriteLine(e); }
}
public override void Stop()
{
acceptConnection.Cancel();
if (socket != null)
{
socketListener.Close();
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(false);
socket.Dispose();
socket = null;
}
}
private void AcceptConnection()
{
acceptConnection = new CancellationTokenSource();
new Thread(delegate()
{
try
{
while (socket == null)
{
if (socketListener.Poll(1, SelectMode.SelectRead))
socket = socketListener.Accept();
acceptConnection.Token.ThrowIfCancellationRequested();
}
Dispatcher.Invoke(delegate ()
{
boutonDemarrer.Content = "Jouer";
boutonDemarrer.IsEnabled = true;
});
}
catch (OperationCanceledException e) { Console.WriteLine("Fin de l'attente de connection ({0})", e.Message); }
}).Start();
}
private void ButtonClickStart(object sender, RoutedEventArgs e)
{
if ((string)boutonDemarrer.Content == "Jouer")
Close();
else if ((string)boutonDemarrer.Content == "Démarrer")
{
Start();
boutonAnnuler.Content = "Stop";
boutonDemarrer.IsEnabled = false;
numPort.IsEnabled = false;
}
}
private void ButtonClickCancel(object sender, RoutedEventArgs e)
{
if ((string)boutonAnnuler.Content == "Annuler")
Close();
else if ((string)boutonAnnuler.Content == "Stop")
{
Stop();
boutonAnnuler.Content = "Annuler";
boutonDemarrer.Content = "Démarrer";
boutonDemarrer.IsEnabled = true;
numPort.IsEnabled = true;
}
}
#region Propriétés
public string Ip { get { return numIp.ToString(); } }
public int Port { get { return (int)numPort.Value; } }
#endregion
#region Membres
private Socket socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private CancellationTokenSource acceptConnection = new CancellationTokenSource();
#endregion
}
客户class:
public partial class Client : Connectable
{
#region Constructeurs
public Client() : this(string.Empty, 12221) { }
public Client(string ipDefaut, int portDefaut)
{
InitializeComponent();
NewMessage += ShowMessage;
numIp.FromString("192.168.2.168");
numPort.Value = portDefaut;
}
#endregion
public override void Start()
{
try
{
socket.Connect(Ip, Port);
boutonConnecter.Content = "Jouer";
numIp.IsEnabled = false;
numPort.IsEnabled = false;
boutonAnnuler.Content = "Déconnecter";
}
catch (SocketException e)
{
Console.WriteLine(e.Message);
}
}
public override void Stop()
{
if (socket.Connected)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
}
private void ButtonClickStart(object sender, RoutedEventArgs e)
{
if ((string)boutonConnecter.Content == "Jouer")
Close();
else if ((string)boutonConnecter.Content == "Connecter")
{
foreach (string num in numIp.ToStringArray())
if (num == string.Empty)
{
ShowMessage("L'adresse ip doit être complète.");
return;
}
Start();
}
}
private void ButtonClickCancel(object sender, RoutedEventArgs e)
{
if ((string)boutonAnnuler.Content == "Annuler")
Close();
else if ((string)boutonAnnuler.Content == "Déconnecter")
{
Stop();
boutonConnecter.IsEnabled = true;
numIp.IsEnabled = true;
numPort.IsEnabled = true;
boutonAnnuler.Content = "Annuler";
boutonConnecter.Content = "Connecter";
}
}
#region Properties
public string Ip { get { return numIp.ToString(); } }
public int Port { get { return (int)numPort.Value; } }
#endregion
}
如果它可以帮助别人...:)
我实际上能够将我的 TcpClient 连接到我的 TcpServer,但我无法让它们通信。我尝试了 client.GetStream()
和 BinaryReader/Writer
.
这是我的代码:
-客户端:
public partial class Client : Window
{
#region Constructeurs
public Client() : this(string.Empty, 12221) { }
public Client(string ipDefaut, int portDefaut)
{
InitializeComponent();
numIp.FromString("192.168.2.168");
numPort.Value = portDefaut;
Serveur serveur = new Serveur();
serveur.Show();
}
#endregion
public void Start()
{
if (Ip == null)
return;
if (client == null || client.Client == null)
client = new TcpClient();
if (client.Connected == true)
{
ShowMessage("Déjà connecté.");
return;
}
client = new TcpClient();
try
{
client.ConnectAsync(Ip, Port).Wait(10);
}
catch (SocketException) { }
}
public void Stop()
{
if (client != null && client.Client != null)
if (client.Connected)
{
client.Client.Shutdown(SocketShutdown.Both);
client.Close();
}
}
public string Read()
{
if (client != null && client.GetStream() != null)
if (client.Connected && client.GetStream().DataAvailable)
{
BinaryReader reader = new BinaryReader(client.GetStream());
return reader.ReadString();
}
return string.Empty;
}
public void Send(string info)
{
if (client != null && client.GetStream() != null)
if (client.Connected)
{
BinaryWriter writer = new BinaryWriter(client.GetStream());
writer.Write(info);
writer.Flush();
}
}
private void ShowMessage(string message)
{
labelInfo.Content = message;
Storyboard sb = Resources["sbLabelInfo"] as Storyboard;
sb.Begin(labelInfo);
}
private void Connecter(object sender, RoutedEventArgs e)
{
foreach (string num in numIp.ToStringArray())
if (num == string.Empty)
{
ShowMessage("L'adresse ip doit être complète.");
return;
}
Start();
if (client.Connected)
{
ShowMessage("Connecté");
boutonConnecter.IsEnabled = false;
numIp.IsEnabled = false;
numPort.IsEnabled = false;
boutonAnnuler.Content = "Déconnecter";
}
else
ShowMessage("Impossible de se connecter.");
}
private void Annuler(object sender, RoutedEventArgs e)
{
if ((string)boutonAnnuler.Content == "Annuler")
Close();
else if ((string)boutonAnnuler.Content == "Déconnecter")
{
Stop();
boutonConnecter.IsEnabled = true;
numIp.IsEnabled = true;
numPort.IsEnabled = true;
boutonAnnuler.Content = "Annuler";
}
}
#region Propriétés
public string Ip { get { return numIp.ToString(); } }
public int Port { get { return (int)numPort.Value; } }
#endregion
#region Membres
private TcpClient client = new TcpClient();
#endregion
}
-服务器:
public partial class Serveur : Window
{
#region Constructeurs
public Serveur() : this(12221) { }
public Serveur(int numPortDefaut)
{
InitializeComponent();
foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
if (addr.AddressFamily == AddressFamily.InterNetwork)
numIp.FromString(addr.ToString());
numPort.Value = numPortDefaut;
serveur = new TcpListener(IPAddress.Parse(Ip), Port);
thread = new Thread(Accept);
serveur.Stop();
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
boutonDemarrer.IsEnabled = false;
MessageBox.Show(this, "Connection impossible - Tic Tac Toe", "Impossible de se connecter à internet. Vérifiez votre connection et réessayez.", MessageBoxButton.OK, MessageBoxImage.Warning);
Close();
}
}
#endregion
public void Start()
{
if (serveur != null)
{
try
{
serveur.Start();
}
catch (SocketException) { }
IsConnected = false;
StartThread();
}
else
{
serveur = new TcpListener(IPAddress.Parse(Ip), Port);
Start();
}
}
public void Stop()
{
if (serveur != null)
{
IsConnected = false;
serveur.Stop();
StopThread();
}
}
public void StartThread()
{
if (thread.ThreadState == ThreadState.Stopped)
thread.Start();
}
public void StopThread()
{
if (!IsConnected)
{
IsConnected = true;
while (thread.IsAlive) { }
IsConnected = false;
}
}
private void Accept()
{
while (!IsConnected && serveur != null)
if (serveur.Pending())
{
client = serveur.AcceptTcpClient();
IsConnected = true;
}
}
public string Read()
{
if (client != null && client.GetStream() != null)
if (client.Connected && client.GetStream().DataAvailable)
{
BinaryReader reader = new BinaryReader(client.GetStream());
return reader.ReadString();
}
return string.Empty;
}
public void Send(string info)
{
if (client != null && client.GetStream() != null)
if (client.Connected)
{
BinaryWriter writer = new BinaryWriter(client.GetStream());
writer.Write(info);
writer.Flush();
}
}
private void Demarrer(object sender, RoutedEventArgs e)
{
Start();
boutonAnnuler.Content = "Stop";
boutonDemarrer.IsEnabled = false;
numPort.IsEnabled = false;
numIp.IsEnabled = false;
}
private void Annuler(object sender, RoutedEventArgs e)
{
if ((string)boutonAnnuler.Content == "Annuler")
{
Stop();
Close();
}
else if ((string)boutonAnnuler.Content == "Stop")
{
StopThread();
boutonAnnuler.Content = "Annuler";
boutonDemarrer.IsEnabled = true;
numPort.IsEnabled = true;
numIp.IsEnabled = true;
}
}
#region Propriétés
public string Ip { get { return numIp.ToString(); } }
public int Port { get { return (int)numPort.Value; } }
public bool IsConnected { get; private set; }
#endregion
#region Membres
private TcpListener serveur = null;
private TcpClient client = null;
private Thread thread = null;
#endregion
}
问题是,在调试模式下,client.GetStream().DataAvailable
return 总是 false
。
为什么 return 会这样,我该如何解决?
(numIp
和numPort
是用户需要填写的部分字段)
试试这个:
//tcp server
public class Server
{
private string ip { get; set; }
private int port { get; set; }
private Socket server { get; set; }
public List<ClientInfo> listClientsConnected { get; private set; }
// delegate for events
public delegate void Client_Connected(ClientInfo c);
public delegate void Client_Message(string msg, ClientInfo c);
public Server(string ip, int port)
{
this.ip = ip;
this.port = port;
this.listClientsConnected = new List<ClientInfo>();
}
// start server
public void Start()
{
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse(this.ip), this.port));
server.Listen(1);
server.BeginAccept(new AsyncCallback(ClientConnected), server);
}
// accept client connection
private void ClientConnected(IAsyncResult res)
{
Socket s = (Socket)res.AsyncState;
Socket client = s.EndAccept(res);
ClientInfo clientInf = new ClientInfo()
{
currentClient = client
};
client.BeginReceive(clientInf.buffer, 0, ClientInfo.BUFFER_SIZE_FOR_MESSAGE, 0, new AsyncCallback(ReceiveMessage), clientInf);
// add client to list
listClientsConnected.Add(clientInf);
if (Cliente_Conneted_Event != null)
Cliente_Conneted_Event(clientInf);
}
// receive message from client
private void ReceiveMessage(IAsyncResult ar)
{
ClientInfo cl = (ClientInfo)ar.AsyncState;
Socket s = cl.currentClient;
int read = s.EndReceive(ar);
string msg = null;
if (read > 0)
{
msg = Encoding.ASCII.GetString(cl.buffer, 0, read);
s.BeginReceive(cl.buffer, 0, ClientInfo.BUFFER_SIZE_FOR_MESSAGE, 0, new AsyncCallback(ReceiveMessage), cl);
}
if (Cliente_Message_Event != null)
Cliente_Message_Event(msg, cl);
}
// send message to client
public void sendMessage(string msg, ClientInfo client)
{
if (client.currentClient != null)
{
if (client.currentClient.Connected && !string.IsNullOrEmpty(msg))
{
client.currentClient.Send(Encoding.ASCII.GetBytes(msg));
}
}
}
//events
public event Client_Connected Cliente_Conneted_Event;
public event Client_Message Cliente_Message_Event;
}
// tcp client
public class Client
{
private Socket client { get; set; }
private string clientName { get; set; }
private string ip { get; set; }
private int port { get; set; }
// delegates
public delegate void Client_Connected(ClientInfo c);
public delegate void Client_Message(string msg, ClientInfo c);
public Client(string ip, int port)
{
this.ip = ip;
this.port = port;
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
// connect client to server
public void Connect()
{
ClientInfo clientInf = new ClientInfo()
{
currentClient = client,
};
client.BeginConnect(new IPEndPoint(IPAddress.Parse(this.ip), this.port), new AsyncCallback(ClientConnected), clientInf);
}
// accept client connection
private void ClientConnected(IAsyncResult res)
{
ClientInfo clientInf = (ClientInfo)res.AsyncState;
clientInf.currentClient.BeginReceive(clientInf.buffer, 0, ClientInfo.BUFFER_SIZE_FOR_MESSAGE, 0, new AsyncCallback(ReceiveMessage), clientInf);
// client connected
if (Cliente_Conneted_Event != null)
Cliente_Conneted_Event(clientInf);
}
// receive message from client
private void ReceiveMessage(IAsyncResult ar)
{
ClientInfo cl = (ClientInfo)ar.AsyncState;
Socket s = cl.currentClient;
int read = s.EndReceive(ar);
string msg = null;
if (read > 0)
{
msg = Encoding.ASCII.GetString(cl.buffer, 0, read);
s.BeginReceive(cl.buffer, 0, ClientInfo.BUFFER_SIZE_FOR_MESSAGE, 0, new AsyncCallback(ReceiveMessage), cl);
}
if (Cliente_Message_Event != null)
Cliente_Message_Event(msg, cl);
}
// send message to client
public void sendMessage(string msg, ClientInfo client)
{
if (client.currentClient != null)
{
if (client.currentClient.Connected && !string.IsNullOrEmpty(msg))
{
client.currentClient.Send(Encoding.ASCII.GetBytes(msg));
}
}
}
public event Client_Connected Cliente_Conneted_Event;
public event Client_Message Cliente_Message_Event;
}
// in my case i used a console application
class Program
{
private static Server server;
static void Main(string[] args)
{
string ip = "127.0.0.1";
int port = 3122;
server = new Server(ip, port);
server.Cliente_Conneted_Event += server_Cliente_Conneted_Event;
server.Start();
// connect client 1
Client client = new Client(ip, port);
client.Connect();
client.Cliente_Message_Event+=client_Cliente_Message_Event;
sendMessageToClient();
Console.ReadKey();
}
//receive message from server
private static void client_Cliente_Message_Event(string msg, ClientInfo c)
{
try {
Console.WriteLine("Msg from Server:"+msg);
}
catch(Exception ex){
Console.WriteLine(ex.Message);
}
}
// client connected to server
private static void server_Cliente_Conneted_Event(ClientInfo c)
{
Console.WriteLine("Client Connected...");
}
// send message to all clients from server
private static void sendMessageToClient()
{
try
{
Console.Write("Msg:");
string msg = Console.ReadLine();
// send message to clients
if (server.listClientsConnected.Count > 0)
{
foreach (ClientInfo client in server.listClientsConnected)
server.sendMessage(msg, client);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
sendMessageToClient();
}
}
}
比预期的要长...我终于放弃 TcpClient/Server 使用自己的套接字。 这是结果(我在我的代码中做了一个抽象 class 因为这些 class 是相似的):
摘要class:
public abstract partial class Connectable : Window
{
public abstract void Start();
public abstract void Stop();
public void WaitMessage()
{
WaitMessage(new StateObject() { socket = socket });
}
private void WaitMessage(StateObject so)
{
Socket s = so.socket;
int read = s.Receive(so.buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None);
so.sb.Append(Encoding.UTF8.GetString(so.buffer, 0, read));
if (s.Available > 0)
WaitMessage(so);
else if (NewMessage != null)
{
NewMessage(so.sb.ToString());
so.sb.Clear();
}
}
public void ReceiveMessage()
{
StateObject state = new StateObject() { socket = socket };
try { socket.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(MessageReceived), state); }
catch (SocketException e) { Console.WriteLine(e.Message); }
}
protected void MessageReceived(IAsyncResult ar)
{
StateObject so = (StateObject)ar.AsyncState;
Socket s = so.socket;
int read = s.EndReceive(ar);
so.sb.Append(Encoding.UTF8.GetString(so.buffer, 0, read));
if (s.Available > 0)
s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(MessageReceived), so);
else if (NewMessage != null)
{
NewMessage(so.sb.ToString());
so.sb.Clear();
}
}
public void SendMessage(string msg)
{
if (socket != null)
{
if (socket.Connected && !string.IsNullOrEmpty(msg))
{
socket.Send(Encoding.UTF8.GetBytes(msg));
}
}
}
protected void ShowMessage(string message)
{
Console.WriteLine(message);
}
public virtual bool IsConnected()
{
if (socket == null)
return false;
return socket.Connected;
}
#region Members
protected Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public Message NewMessage;
#endregion
#region Delegates
public delegate void Message(string message);
#endregion
}
服务器class:
public partial class Server : Connectable
{
#region Constructeurs
public Server() : this(12221) { }
public Server(int numPortDefaut)
{
InitializeComponent();
socket = null;
NewMessage += ShowMessage;
foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
if (addr.AddressFamily == AddressFamily.InterNetwork)
numIp.FromString(addr.ToString());
numPort.Value = numPortDefaut;
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
boutonDemarrer.IsEnabled = false;
MessageBox.Show(this, "Connection impossible - Tic Tac Toe", "Impossible de se connecter à internet. Vérifiez votre connection et réessayez.", MessageBoxButton.OK, MessageBoxImage.Warning);
Close();
}
}
#endregion
public override void Start()
{
if (socketListener.IsBound)
{
if (socket != null)
{
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(false);
socket.Dispose();
socket = null;
}
socketListener.Close();
socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
try
{
socketListener.Bind(new IPEndPoint(IPAddress.Parse(Ip), Port));
socketListener.Listen(1);
AcceptConnection();
}
catch (SocketException e) { Console.WriteLine(e); }
}
public override void Stop()
{
acceptConnection.Cancel();
if (socket != null)
{
socketListener.Close();
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(false);
socket.Dispose();
socket = null;
}
}
private void AcceptConnection()
{
acceptConnection = new CancellationTokenSource();
new Thread(delegate()
{
try
{
while (socket == null)
{
if (socketListener.Poll(1, SelectMode.SelectRead))
socket = socketListener.Accept();
acceptConnection.Token.ThrowIfCancellationRequested();
}
Dispatcher.Invoke(delegate ()
{
boutonDemarrer.Content = "Jouer";
boutonDemarrer.IsEnabled = true;
});
}
catch (OperationCanceledException e) { Console.WriteLine("Fin de l'attente de connection ({0})", e.Message); }
}).Start();
}
private void ButtonClickStart(object sender, RoutedEventArgs e)
{
if ((string)boutonDemarrer.Content == "Jouer")
Close();
else if ((string)boutonDemarrer.Content == "Démarrer")
{
Start();
boutonAnnuler.Content = "Stop";
boutonDemarrer.IsEnabled = false;
numPort.IsEnabled = false;
}
}
private void ButtonClickCancel(object sender, RoutedEventArgs e)
{
if ((string)boutonAnnuler.Content == "Annuler")
Close();
else if ((string)boutonAnnuler.Content == "Stop")
{
Stop();
boutonAnnuler.Content = "Annuler";
boutonDemarrer.Content = "Démarrer";
boutonDemarrer.IsEnabled = true;
numPort.IsEnabled = true;
}
}
#region Propriétés
public string Ip { get { return numIp.ToString(); } }
public int Port { get { return (int)numPort.Value; } }
#endregion
#region Membres
private Socket socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private CancellationTokenSource acceptConnection = new CancellationTokenSource();
#endregion
}
客户class:
public partial class Client : Connectable
{
#region Constructeurs
public Client() : this(string.Empty, 12221) { }
public Client(string ipDefaut, int portDefaut)
{
InitializeComponent();
NewMessage += ShowMessage;
numIp.FromString("192.168.2.168");
numPort.Value = portDefaut;
}
#endregion
public override void Start()
{
try
{
socket.Connect(Ip, Port);
boutonConnecter.Content = "Jouer";
numIp.IsEnabled = false;
numPort.IsEnabled = false;
boutonAnnuler.Content = "Déconnecter";
}
catch (SocketException e)
{
Console.WriteLine(e.Message);
}
}
public override void Stop()
{
if (socket.Connected)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
}
private void ButtonClickStart(object sender, RoutedEventArgs e)
{
if ((string)boutonConnecter.Content == "Jouer")
Close();
else if ((string)boutonConnecter.Content == "Connecter")
{
foreach (string num in numIp.ToStringArray())
if (num == string.Empty)
{
ShowMessage("L'adresse ip doit être complète.");
return;
}
Start();
}
}
private void ButtonClickCancel(object sender, RoutedEventArgs e)
{
if ((string)boutonAnnuler.Content == "Annuler")
Close();
else if ((string)boutonAnnuler.Content == "Déconnecter")
{
Stop();
boutonConnecter.IsEnabled = true;
numIp.IsEnabled = true;
numPort.IsEnabled = true;
boutonAnnuler.Content = "Annuler";
boutonConnecter.Content = "Connecter";
}
}
#region Properties
public string Ip { get { return numIp.ToString(); } }
public int Port { get { return (int)numPort.Value; } }
#endregion
}
如果它可以帮助别人...:)