网络聊天室

---------------------- ASP.Net+Android+IO开发S.Net培训、期待与您交流! ----------------------

服务端

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

namespace MyChatroomServer
{
    public partial class MyChatroomServer : Form
    {
        public MyChatroomServer()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false; //关闭对文本框的跨线程操作
        }
        Thread threadWatch = null;//负责监听客户端连接请求的线程
        Socket SocketWatch = null;//负责监听的套接字
        Socket sokConnectin = null;//负责通信的套接字
        Thread threadRec = null;
        Socket sokRec = null;
        //保存服务器端所有负责和客户端通信的套接字
        Dictionary<string, Socket> dic = new Dictionary<string, Socket>();
        //保存服务器端所有负责调用通信套接字.Receive()方法的线程
        Dictionary<string, Thread> dicThread = new Dictionary<string, Thread>();
        private void btnListen_Click(object sender, EventArgs e)
        {
            //创建负责监听的套接字,参数(使用ip4寻址协议,使用流式连接,使用tcp协议)
            SocketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //获得文本框中的IP地址对象
            IPAddress address = IPAddress.Parse(txtIp.Text.Trim());
            //创建包含IP和Port的网络节点对象
            IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));
            //将负责监听的套接字绑定到唯一个IP和端口上
            SocketWatch.Bind(endpoint);
            //设置监听队列的长度
            SocketWatch.Listen(10);

            //创建负责监听的线程,并传入方法
            threadWatch = new Thread(WatchConnecting);
            threadWatch.IsBackground = true;//设置为后台线程
            threadWatch.Start();//开启线程
            showMsg("服务器启动监听成功");
        }

        void WatchConnecting()
        {
            while (true)
            {
                //开始监听客户端的请求,注意:accept方法会阻断当前线程
                sokConnectin = SocketWatch.Accept();//一但监听到客户端的请求,就返回一个负责和该客户
                //将与客户端通信的套接字对象sokConnectin添加到键值中,并以IP作为标识
                dic.Add(sokConnectin.RemoteEndPoint.ToString(), sokConnectin);
                //向列表控件中添加一个客户端ip端口字符串,作为客户的唯一标示
                lbOnline.Items.Add(sokConnectin.RemoteEndPoint.ToString());
                //端通信的sokconnection

                threadRec = new Thread(receiveMsg);
                showMsg("客户端连接成功");

                threadRec.SetApartmentState(ApartmentState.STA);
                threadRec.IsBackground = false;
                threadRec.Start(sokConnectin);
                dicThread.Add(sokConnectin.RemoteEndPoint.ToString(), threadRec);
            }
        }
        void receiveMsg(object sokConnectinPara)
        {
            Socket sokConnectin = sokConnectinPara as Socket;
            while (true)
            {
                //定义一个接收用的缓存(字节数组)
                byte[] arrMsgRec = new byte[1024 * 1024];
                //将接收到的数据存入arrMsgRec数组
                int length = -1;
                try
                {
                  length = sokConnectin.Receive(arrMsgRec);
                }
                catch (SocketException ex)
                {
                    showMsg("异常:" + ex.Message);
                    dic.Remove(sokConnectin.RemoteEndPoint.ToString());
                    dicThread.Remove(sokConnectin.RemoteEndPoint.ToString());
                    lbOnline.Items.Remove(sokConnectin.RemoteEndPoint.ToString());
                    break;
                }
                catch (Exception ex)
                {
                    showMsg("异常:" + ex.Message);
                    break;
                }
                if (arrMsgRec[0] == 0)//判断发送过来的是文字还是文件
                {

                    string msg = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length - 1);
                    showMsg(msg);
                }
                else if (arrMsgRec[0] == 1)
                {

                    SaveFileDialog sfd = new SaveFileDialog();
                    if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        string fileSavePath = sfd.FileName;//获得要保存的文件
                        //创建文件流,让后让文件流根据路径创建一个文件
                        using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))
                        {
                            fs.Write(arrMsgRec, 1, length - 1);
                            showMsg("文件保存成功:" + fileSavePath);
                        }
                    }

                }
            }
        }
        void showMsg(string msg)
        {
            txtMsg.AppendText(msg + "
");
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(lbOnline.Text))
            {
                showMsg("请选择发送对象");
            }
            else
            {
                string msg = txtMsgSend.Text.Trim();
                //将要发送的字符串转成UTF8对应的字节数组
                byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(msg);

                string strClintKey = lbOnline.Text;
                try
                {
                    dic[strClintKey].Send(arrMsg);
                }
                catch (SocketException ex)
                {
                    showMsg("异常:" + ex.Message);

                }
                catch (Exception ex)
                {
                    showMsg("异常:" + ex.Message);
                }
                //  sokConnectin.Send(arrMsg);
                showMsg("发送了数据出去" + msg);
            }
        }

        private void btnSendAll_Click(object sender, EventArgs e)
        {
            string msg = txtMsgSend.Text.Trim();
            //将要发送的字符串转成UTF8对应的字节数组
            byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(msg);
            foreach (Socket s in dic.Values)
                s.Send(arrMsg);
            //  sokConnectin.Send(arrMsg);
            showMsg("群发了:" + msg);
        }
    }
}

客户端

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

namespace MyChatroomClint
{
    public partial class MyChatroomClient : Form
    {
        public MyChatroomClient()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }
        Thread threadClinet = null;//客户端负责监听服务端线程的消息
        Socket socketClient = null;
        private void btnconnect_Click(object sender, EventArgs e)
        {
            IPAddress address = IPAddress.Parse(txtIp.Text.Trim());//获得IP
            IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));//网络节点,创建客户端套接字
            socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //向指定的IP端口发送请求
            socketClient.Connect(endpoint);
            //创建线程
            threadClinet = new Thread(receiveMsg);
            threadClinet.IsBackground = true;
            threadClinet.Start();
           

        }
        void receiveMsg()
        {
            while (true)
            {
                //定义一个接收用的缓存(字节数组)
                byte[] arrMsgRec = new byte[1024 * 1024];
                //将接收到的数据存入arrMsgRec数组
                int length=socketClient.Receive(arrMsgRec);
                string msg = System.Text.Encoding.UTF8.GetString(arrMsgRec,0,length);
                showMsg(msg);
            }
        }
         

        void showMsg(string msg)
        {
            txtMsg.AppendText(msg + "
");
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            string msg = txtMsgSend.Text.Trim();
            byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(msg);
            byte[] arrMsgSend = new byte[arrMsg.Length + 1];
            arrMsgSend[0] = 0;
            arrMsg.CopyTo(arrMsgSend,1);
           // Buffer.BlockCopy(arrMsg, 0, arrMsgSend, 1, arrMsg.Length );
            socketClient.Send(arrMsgSend);
            showMsg("发送了数据出去" + msg);


        }

        //选择要发送的文件
        private void btnChoseFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                txtFilePath.Text = ofd.FileName;
            }
            
        }
        //向服务器端发送文件
        private void btnSendFile_Click(object sender, EventArgs e)
        {
            //用文件流打开用户选择的文件
            using (FileStream fs = new FileStream(txtFilePath.Text, FileMode.Open))
            {
                byte[] arrFile = new byte[1024 * 1024*2];//定义一个2M的缓存区
                //将文件数据读到数组arrFile中,并获得真实长度Length
                int length = fs.Read(arrFile,0,arrFile .Length);
                byte[] arrFileSend = new byte[length + 1];
                arrFileSend[0] = 1;//1代表发送的是文件数据
                //将arrFile数组里的元素从第0个开始拷贝,拷贝到arrFileSend数组里,从第1个位置开始存放,一共拷贝length个数据
                Buffer.BlockCopy(arrFile, 0, arrFileSend, 1, length);
                //arrFile.CopyTo(arrFileSend, 1);//另外一种方法,从第一个位置开始复制
                socketClient.Send(arrFileSend);//发送了包含表示符的文件
                showMsg("文件发送完毕");
                
            }
        }
    }
}

---------------------- ASP.Net+Android+IO开发S.Net培训、期待与您交流! ----------------------

原文地址:https://www.cnblogs.com/qwsdxz/p/3171553.html