无法 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 会这样,我该如何解决?

numIpnumPort是用户需要填写的部分字段)

试试这个:

  //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
}

如果它可以帮助别人...:)