C#利用TcpListener和TcpClient类实现服务器和客户端的通信

注:只能在服务器和客户端不再同一台PC上实现通信,同一台PC无法利用封装的类实现客户端与服务器通信!!!

由于还是初学C#,目前还不知道什么原因!!!记录下...

网络聊天系统:

服务器相关:

首先声明一个用户相关的类:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace TcpService_ListenerAndClient
{
    public class TcpServiceBSD
    {

        private BinaryReader _br;
        private BinaryWriter _bw;
        private TcpClient _client;
        private string _userName;

        

        public BinaryReader Br
        {
            get
            {
                return _br;
            }

            set
            {
                _br = value;
            }
        }

        public BinaryWriter Bw
        {
            get
            {
                return _bw;
            }

            set
            {
                _bw = value;
            }
        }

        public TcpClient Client
        {
            get
            {
                return _client;
            }

            set
            {
                _client = value;
            }
        }

        public string UserName
        {
            get
            {
                return _userName;
            }

            set
            {
                _userName = value;
            }
        }

        public TcpServiceBSD(TcpClient client/*,string _localIp,int _localPort*/)
        {
            this.Client = client;
            NetworkStream networkStream = client.GetStream();
            Br = new BinaryReader(networkStream);
            Bw = new BinaryWriter(networkStream);

            //this.LocalIpAddress = IPAddress.Parse(_localIp);
            //this.LocalPort = _localPort;
        }

        public void Close()
        {
            Br.Close();
            Bw.Close();
            this.Client.Close();
        }
    }
}
UI界面的:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TcpService_ListenerAndClient
{
    public partial class TcpService : Form
    {
        //public Dictionary dicTcpClient = new Dictionary();
        //声明一个存放用户的集合
        private List userList = new List();
        //声明本地IP地址
        IPAddress localAddress;
        //声明本地端口号
        private const int localPort = 5000;
        //声明用来监听的对象
        private TcpListener myListener;
        //指示是否正常退出
        bool isNormalExit = false;

        //public delegate void AddMsgToText(string text);
        //声明一个跨线程的委托实现对ListBox的操作
        public delegate void AddMsgToListBox(string str);

        //void AddMsgToTxtLog(string str)
        //{
        //    if(txtLog.InvokeRequired)
        //    {
        //        AddMsgToText addMsgToText = new AddMsgToText(AddMsgToTxtLog);
        //        txtLog.Invoke(addMsgToText, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd hh:mm:ss.fff") + " "+str);
        //    }
        //    else
        //    {
        //        txtLog.AppendText(DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd hh:mm:ss.fff") + " " + str);
        //    }
        //}

        //声明一个跨线程的委托实现对ListBox的操作
        void AddMsgToLtbUsers(string str)
        {
            if(ltbUsers.InvokeRequired)
            {
                AddMsgToListBox addMsgToListBox= new AddMsgToListBox(AddMsgToLtbUsers);
                ltbUsers.Invoke(addMsgToListBox, str);
            }
            else
            {
                ltbUsers.Items.Add(str);
                ltbUsers.SelectedIndex = ltbUsers.Items.Count - 1;
                ltbUsers.ClearSelected();
            }
        }

        public TcpService()
        {
            InitializeComponent();

            //获取本地IP地址,以及设置界面相关的属性
            ltbUsers.HorizontalScrollbar = true;
            IPAddress[] addrIp = Dns.GetHostAddresses(Dns.GetHostName());
            localAddress = addrIp[addrIp.Length -1];

            txtLocalIp.Text = localAddress.ToString();
            txtLocalListenPort.Text = localPort.ToString();

            txtSendMsg.Enabled = false;
            btnSendMsg.Enabled = false;
            btnStopListen.Enabled = false;
            txtLocalIp.Enabled = false;
            txtLocalListenPort.Enabled = false;
        }

        private void TcpService_Load(object sender, EventArgs e)
        {

        }

        //开始监听按钮
        private void btnStartListen_Click(object sender, EventArgs e)
        {
            //实例化监听对象
            myListener = new TcpListener(localAddress, localPort);
           //开启监听
            myListener.Start();
            //AddMsgToTxtLog("开始在:" + localAddress.ToString() + localPort.ToString() + "监听客户连接");
            AddMsgToLtbUsers(string.Format("开始在{0}:{1}监听客户连接", localAddress, localPort));
            //开起一个用来监听的后台线程
            Thread myThread = new Thread(ListenClientConnect);
            myThread.Start();

            btnStartListen.Enabled = false;
            btnStopListen.Enabled = true;
        }

        //监听后台线程执行的方法
        private void ListenClientConnect()
        {
            //声明一个用来存储连接对象的TcpClient对象
            TcpClient newClient = null;
            while(true)
            {
                try
                {
                    //接收该对象
                    newClient = myListener.AcceptTcpClient();
                }
                catch
                {
                    break;
                }

                //将该用户的相关信息使用封装的类存储
                TcpServiceBSD tcpServerBSD = new TcpServiceBSD(newClient);
                //开启一个不停接收的线程
                Thread threadReceive = new Thread(ReceiveData);
                threadReceive.Start(tcpServerBSD);
                //将接收的用户存储到集合中并显示在ListBox控件中
                userList.Add(tcpServerBSD);
                //AddMsgToTxtLog(newClient.Client.RemoteEndPoint.ToString() + "进入.");
                //AddMsgToTxtLog("当前连接的用户数:" + userList.Count.ToString() + ".");
                AddMsgToLtbUsers(string.Format("[{0}]进入", newClient.Client.RemoteEndPoint));
                AddMsgToLtbUsers(string.Format("当前连接用户数:{0}", userList.Count));
            }
        }

        //接收监听端口发送的数据
        private void ReceiveData(object userState)
        {
            TcpServiceBSD user = userState as TcpServiceBSD;
            TcpClient client = user.Client;
            while(isNormalExit ==false)
            {
                string receiveString = null;
                try
                {
                    //用BinaryReader的方法读取网络流中的数据
                    receiveString = user.Br.ReadString();
                }
                catch
                {
                    if(isNormalExit ==false)
                    {
                        //AddMsgToTxtLog("已与" + client.Client.RemoteEndPoint.ToString() + "失去联系,已终止接收该用户信息");
                        AddMsgToLtbUsers(string.Format("与{0}失去联系,,已终止接收该用户信息", client.Client.RemoteEndPoint));
                        RemoveUser(user);
                    }
                    break;
                }
                //AddMsgToTxtLog("来自:" + user.Client.Client.RemoteEndPoint.ToString() + ":" + receiveString);
                AddMsgToLtbUsers(string.Format("来自:[{0}]:{1}", user.Client.Client.RemoteEndPoint, receiveString));
                string[] splitString = receiveString.Split(',');
                switch (splitString[0])
                {
                    case "Login":
                        {
                            user.UserName = splitString[1];
                            SendToAllClient(user, receiveString);
                            break;
                        }
                    case "Logout":
                        {
                            SendToAllClient(user, receiveString);
                            RemoveUser(user);
                            return;
                        }
                    case "Talk":
                        {
                            string talkString = receiveString.Substring(splitString[0].Length + splitString[1].Length + 2);
                            //AddMsgToTxtLog(user.UserName + "对" + splitString[1] + "说:" + talkString);
                            AddMsgToLtbUsers(string.Format("[{0}]对[{1}]说:{2}", user.UserName, splitString[1], talkString));
                            SendToClient(user, "talk," + user.UserName + "," + talkString);
                            foreach(TcpServiceBSD target in userList)
                            {
                                if(target.UserName ==splitString[1] && user.UserName != splitString[1])
                                {
                                    SendToClient(target, "talk," + user.UserName + "," + talkString);
                                    break;
                                }
                            }
                            break;
                        }
                    default:
                        {
                            //AddMsgToTxtLog("什么意思啊:" + receiveString);
                            AddMsgToLtbUsers(string.Format("什么意思啊:{0}", receiveString));
                            break;
                        }
                }
            }
        }

        private void SendToClient(TcpServiceBSD user,string message)
        {
            try
            {
                //利用BinaryWriter的方法向网络流中写入数据
                user.Bw.Write(message);
                user.Bw.Flush();
                //AddMsgToTxtLog("向" + user.UserName + "发送:" + message);
                AddMsgToLtbUsers(string.Format("向[{0}]发送:{1}", user.UserName, message));
            }
            catch
            {
                //AddMsgToTxtLog("向" + user.UserName + "发送信息失败");
                AddMsgToLtbUsers(string.Format("向[{0}]发送信息失败!", user.UserName));

            }
        }

        private void SendToAllClient(TcpServiceBSD user,string message)
        {
            string command = message.Split(',')[0].ToLower();
            if(command =="login")
            {
                for(int i =0;i< userList.Count;i++)
                {
                    SendToClient(userList[i], message);
                    if(userList[i].UserName != user.UserName)
                    {
                        SendToClient(user, "login," + userList[i].UserName);
                    }
                }
            }
            else if(command == "logout")
            {
                for (int i = 0; i < userList.Count; i++)
                {
                    if (userList[i].UserName != user.UserName)
                    {
                        SendToClient(userList[i], message);
                    }
                }
            }
        }

        private void RemoveUser(TcpServiceBSD user)
        {
            userList.Remove(user);
            user.Close();
            //AddMsgToTxtLog(string.Format("当前连接的用户数:{0}", userList.Count));
            AddMsgToLtbUsers(string.Format("当前连接的用户数:{0}", userList.Count));
        }

        private void btnStopListen_Click(object sender, EventArgs e)
        {
            AddMsgToLtbUsers("开始停止服务,并依次使用户退出!");
            isNormalExit = true;
            for(int i=userList.Count-1;i>=0;i--)
            {
                RemoveUser(userList[i]);
            }
            myListener.Stop();
            btnStartListen.Enabled = true;
            btnStopListen.Enabled = false;
        }

        private void TcpService_FormClosing(object sender, FormClosingEventArgs e)
        {
            if(myListener !=null)
            {
                btnStopListen.PerformClick();
            }
        }
    }
}

客户端:

UI界面相关:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TcpClient_Client
{
    public partial class TcpClientForm : Form
    {
        private bool isExit = false;
        private TcpClient client;
        private BinaryReader br;
        private BinaryWriter bw;

        public TcpClientForm()
        {
            InitializeComponent();
            //产生一个随机的用户名
            Random r = new Random((int)DateTime.Now.Ticks);
            txtUserName.Text = "user" + r.Next(100, 999);
            ltbCurrentOnline.HorizontalScrollbar = true;

            txtServiceIp.Enabled = false;
            txtServicePort.Enabled = false;
            btnSatrtConnect.Enabled = false;
            btnStopConnect.Enabled = false;
        }

        private void TcpClient_Load(object sender, EventArgs e)
        {

        }

        private void btnLogin_Click(object sender, EventArgs e)
        {
            btnLogin.Enabled = false;
            try
            {
                //本地发送端的先关地址信息及端口号
                IPAddress iep = IPAddress.Parse("192.168.1.114");
                IPEndPoint ip = new IPEndPoint(iep, 50000);
            //连接的远程主机的地址及端口号信息
            IPAddress remIp = IPAddress.Parse("192.168.1.150");
            IPEndPoint remIep = new IPEndPoint(remIp, 50000);

            
            client = new TcpClient(ip);
                //client.Connect(ip);
                client.Connect(remIp, 50000);
                //client = new TcpClient(Dns.GetHostName(), 50000);
                txtServiceIp.Text = client.Client.RemoteEndPoint.ToString();

                AddTalkMessage("连接成功");
            }
            catch
            {
                AddTalkMessage("连接失败");
                btnLogin.Enabled = true;
                return;
            }
            NetworkStream networkStream = client.GetStream();
            br = new BinaryReader(networkStream);
            bw = new BinaryWriter(networkStream);
            SendMessage("Login," + txtUserName.Text);
            Thread threadReceive = new Thread(new ThreadStart(ReceiveData));
            threadReceive.IsBackground = true;
            threadReceive.Start();
        }

        private void ReceiveData()
        {
            string receiveString = null;
            while(isExit ==false)
            {
                try
                {
                    receiveString = br.ReadString();
                }
                catch
                {
                    if(isExit ==false)
                    {
                        MessageBox.Show("与服务器失去联系!");
                    }
                    break;
                }
                string[] splitString = receiveString.Split(',');
                string command = splitString[0].ToLower();
                switch(command)
                {
                    case "login":
                        {
                            AddOnline(splitString[1]);
                            break;
                        }
                    case "logout":
                        {
                            RemoveUserName(splitString[1]);
                            break;
                        }
                    case "talk":
                        {
                            AddTalkMessage(splitString[1] + ":\r\n");
                            AddTalkMessage(receiveString.Substring(splitString[0].Length + splitString[1].Length + 2));
                            break;
                        }
                    default:
                        {
                            AddTalkMessage("什么意思啊:" + receiveString);
                            break;
                        }                       
                }
            }
            Application.Exit();
        }

        private void SendMessage(string message)
        {
            try
            {
                bw.Write(message);
                bw.Flush();
            }
            catch
            {
                AddTalkMessage("发送失败!");
            }
        }

        private void btnSendMsg_Click(object sender, EventArgs e)
        {
            if(ltbCurrentOnline.SelectedIndex !=-1)
            {
                SendMessage("Talk," + ltbCurrentOnline.SelectedItem + "," + txtSendMsg.Text + "\r\n");
                txtSendMsg.Clear();
            }
            else
            {
                MessageBox.Show("请在【当前在线用户】中选择一个对话者");
            }
        }

        private void TcpClientForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if(client !=null)
            {
                SendMessage("Logout," + txtUserName.Text);
                isExit = true;
                br.Close();
                bw.Close();
                client.Close();
            }
        }

        private delegate void MessageDelegate(string message);

        private void AddTalkMessage(string message)
        {
            if(txtLog.InvokeRequired)
            {
                MessageDelegate d = new MessageDelegate(AddTalkMessage);
                txtLog.Invoke(d,new object[] { message });
            }
            else
            {
                txtLog.AppendText(message + Environment.NewLine);
                txtLog.ScrollToCaret();
            }
        }

        private delegate void AddOnlineDelegate(string message);

        private void AddOnline(string userName)
        {
            if(ltbCurrentOnline.InvokeRequired)
            {
                AddOnlineDelegate d = new AddOnlineDelegate(AddOnline);
                ltbCurrentOnline.Invoke(d, new object[] { userName });
            }
            else
            {
                ltbCurrentOnline.Items.Add(userName);
                ltbCurrentOnline.SelectedIndex = ltbCurrentOnline.Items.Count - 1;
                ltbCurrentOnline.ClearSelected();
            }
        }

        private delegate void RemoveUserNameDelegate(string userName);

        private void RemoveUserName(string userName)
        {
            if (ltbCurrentOnline.InvokeRequired)
            {
                RemoveUserNameDelegate d = new RemoveUserNameDelegate(RemoveUserName);
                ltbCurrentOnline.Invoke(d, new object[] { userName });
            }
            else
            {
                ltbCurrentOnline.Items.Remove(userName);
                ltbCurrentOnline.SelectedIndex = ltbCurrentOnline.Items.Count - 1;
                ltbCurrentOnline.ClearSelected();
            }
        }


        private void btnSatrtConnect_Click(object sender, EventArgs e)
        {
            try
            {
                IPAddress iep = IPAddress.Parse("192.168.1.150");
                IPEndPoint ip = new IPEndPoint(iep, 50000);

                //client = new TcpClient("192.168.1.150", 50000);
                client = new TcpClient(ip);
                client.Connect(ip);
                txtServiceIp.Text = client.Client.RemoteEndPoint.ToString();

                AddTalkMessage("连接成功");
            }
            catch
            {
                AddTalkMessage("连接失败");
                btnLogin.Enabled = true;
                return;
            }
            NetworkStream networkStream = client.GetStream();
            br = new BinaryReader(networkStream);
            bw = new BinaryWriter(networkStream);
            SendMessage("Login," + txtUserName.Text);
            Thread threadReceive = new Thread(new ThreadStart(ReceiveData));
            threadReceive.IsBackground = true;
            threadReceive.Start();
        }
    }
}



你可能感兴趣的:(C#利用TcpListener和TcpClient类实现服务器和客户端的通信)