zoukankan      html  css  js  c++  java
  • (C#:Socket)简单的服务端与客户端通信。

    要求:
    1.可以完成一对一的通信;
    2.实现服务端对客户端一对多的选择发送;
    3.可以实现服务端的群发功能;
    4.可以实现客户端文件的发送;

    要点:
    服务器端:
    第一步:用指定的端口号和服务器的ip建立一个EndPoint对像;
    第二步:建立一个Socket对像;
    第三步:用socket对像的Bind()方法绑定EndPoint;
    第四步:用socket对像的Listen()方法开始监听;
    第五步:接受到客户端的连接,用socket对像的Accept()方法创建新的socket对像用于和请求的客户端进行通信;
    第六步:通信结束后一定记得关闭socket;

    客户端:
    第一步:用指定的端口号和服务器的ip建立一个EndPoint对像;
    第二步:建立一个Socket对像;
    第三步:用socket对像的Connect()方法以上面建立的EndPoint对像做为参数,向服务器发出连接请求;
    第四步:如果连接成功,就用socket对像的Send()方法向服务器发送信息;
    第五步:用socket对像的Receive()方法接受服务器发来的信息 ;
    第六步:通信结束后一定记得关闭socket;

    服务端代码如下:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using System.IO;
    
    namespace Socket_ServerAndClient
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                TextBox.CheckForIllegalCrossThreadCalls = false;
            }
    
            Thread threadWatch = null;
            Socket socketWatch = null;
    
            /// <summary>
            /// 创建服务
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void button1_Click(object sender, EventArgs e)
            {
                socketWatch = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
                IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
                IPEndPoint endpoint = new IPEndPoint(address,int.Parse(txtPort.Text.Trim()));
                socketWatch.Bind(endpoint);
                socketWatch.Listen(10);
                threadWatch = new Thread(WatchConnection);
                threadWatch.IsBackground = true;
                threadWatch.Start();           
                ShowMsg("服务器监听成功......");
            }
    
            
            //Socket sokConnection = null;
            Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
            Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();
    
            /// <summary>
            /// 监听客户端的请求方法
            /// </summary>
            /// <param name="obj"></param>
            private void WatchConnection(object obj)
            {
                while (true)
                {
                    // 负责通信的套接字
                    Socket sokConnection = socketWatch.Accept();
                    lb_Online.Items.Add(sokConnection.RemoteEndPoint.ToString());
                    dict.Add(sokConnection.RemoteEndPoint.ToString(),sokConnection);
                    
                    //创建通信线程
                    ParameterizedThreadStart pts = new ParameterizedThreadStart(RecMsg);// 委托
                    Thread thr = new Thread(pts);
                    thr.IsBackground = true;
                    thr.Start(sokConnection);
                    dictThread.Add(sokConnection.RemoteEndPoint.ToString(),thr);
    
                    ShowMsg("客户端连接成功......"+sokConnection.RemoteEndPoint.ToString());
                }           
            }
    
            /// <summary>
            /// 服务端负责监听客户端发送消息的方法
            /// </summary>
            void RecMsg(object socketClient)
            {
                Socket socketClients = socketClient as Socket;
                while (true)
                {
                    byte[] arrMsgRec = new byte[1024 * 1024 * 2];
    
                    int length = -1;
                    try
                    {
                        length = socketClients.Receive(arrMsgRec);
                    }
                    catch (SocketException ex)
                    {
                        ShowMsg("异常:" + ex.Message);
                        // 从 通信套接字 集合中删除被中断连接的套接字对象
                        dict.Remove(socketClients.RemoteEndPoint.ToString());
                        // 从 通信线程 集合中删除被中断连接的套接字对象
                        dictThread.Remove(socketClients.RemoteEndPoint.ToString());
                        // 从 列表 中移除 IP&Port
                        lb_Online.Items.Remove(socketClients.RemoteEndPoint.ToString());
                        break;
                    }
                    catch (Exception ex)
                    {
                        ShowMsg("异常:" + ex.Message);
                        break;
                    }
                    // 判断第一个发送过来的数据如果是1,则代表发送过来的是文本数据
                    if (arrMsgRec[0] == 0)
                    {
                        string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length-1);
                        ShowMsg(strMsgRec);
                    }
                    // 若是1则发送过来的是文件数据(文档,图片,视频等。。。)
                    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);
                            }
                        }
                    }               
                }
            }
    
            private void ShowMsg(string p)
            {
                txtMsg.AppendText(p+"
    ");
            }
    
            /// <summary>
            /// 发送消息
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void Send_Click_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(lb_Online.Text))
                {
                    MessageBox.Show("请选择发送的好友!!!");
                }
                else
                { 
                    string strMsg = tb_Msg_Send.Text.Trim();
                    byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                    string strClientKey = lb_Online.Text;
                    try
                    {
                        dict[strClientKey].Send(arrMsg);
                        ShowMsg("发送了数据出去:"+strMsg);
                    }
                    catch (SocketException ex)
                    {
                        ShowMsg("发送时异常:" + ex.Message);
                    }
                    catch(Exception ex)
                    {
                        ShowMsg("发送时异常:" + ex.Message);
                    }
                    // sokConnection.Send(arrMsg);
                    ShowMsg("发送了数据出去:"+strMsg);
                }
            }
    
            /// <summary>
            /// 群发消息
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void SendToAll_Click(object sender, EventArgs e)
            {
                string strMsg = txtMsg.Text.Trim();
                byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                foreach (Socket item in dict.Values)
                {
                    item.Send(arrMsg);
                }
                ShowMsg("群发完毕!!!:)");
            }
        }
    }
    

      

    客户端代码如下:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using System.IO;
    
    namespace Socket_Client
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                TextBox.CheckForIllegalCrossThreadCalls = false;
            }
    
            Thread threadRec = null;
            Socket socketClient = null;
    
            private void btn_Connect_Click(object sender, EventArgs e)
            {
                IPAddress address = IPAddress.Parse(tb_IP.Text.Trim());
                IPEndPoint endport = new IPEndPoint(address,int.Parse(tb_Port.Text.Trim()));
                socketClient = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
                socketClient.Connect(endport);
    
                threadRec = new Thread(RecMsg);
                threadRec.IsBackground = true;
                threadRec.Start();
            }
    
            void RecMsg()
            {
                while (true)
                {
                    byte[] arrMsgRec = new byte[1024*1024*2];
                    int length = socketClient.Receive(arrMsgRec);
                    string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec,0,length);
                    ShowMsg(strMsgRec);
                }
            }
    
    
            private void ShowMsg(string msg)
            {
                tb_Msg.AppendText(msg+"
    ");
            }
    
            private void btnSendMsg_Click(object sender, EventArgs e)
            {
                string strMsg = txtMsgSend.Text.Trim();
                byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                byte[] arrMsgSend = new byte[arrMsg.Length];
                // 添加标识位,0代表发送的是文字
                arrMsgSend[0] = 0;
                Buffer.BlockCopy(arrMsg, 0, arrMsgSend, 1, arrMsg.Length);
                socketClient.Send(arrMsg);
                ShowMsg("I say:"+strMsg);
            }
    
            /// <summary>
            /// 选择文件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btChoseFile_Click(object sender, EventArgs e)
            {
                OpenFileDialog ofd = new OpenFileDialog();
                if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    txtFilePath.Text = ofd.FileName;
                }
            }
    
            /// <summary>
            /// 发送文件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btSendFile_Click(object sender, EventArgs e)
            {
                using (FileStream fs = new FileStream())
                { 
                    byte[] arrFile = new byte[1024*1024*2];
                    int length = fs.Read(arrFile, 0, arrFile.Length);
                    byte[] arrFileSend = new byte[length+1];
                    arrFileSend[0] = 1;// 代表文件数据
                    // 将数组 arrFile 里的数据从第零个数据拷贝到 数组 arrFileSend 里面,从第1个开始,拷贝length个数据
                    Buffer.BlockCopy(arrFile, 0, arrFileSend, 1, length);
                    socketClient.Send(arrFileSend);
                }
            }
        }
    }
    

    程序运行截图:

      

  • 相关阅读:
    python入门1
    查找字段 和查找组件
    DBGRID 拖动滚动条 和 鼠标滚轮的问题
    数据集 过滤时 RecordCount 属性
    查找字段 如何 过滤
    数据集控件 放在 数据模块 上后,如何写事件代码
    取TTable 过滤后的记录数
    判断 Windows操作系统是32位还是64位
    MatchText MatchStr 区别
    EClassNotFound
  • 原文地址:https://www.cnblogs.com/IamJiangXiaoKun/p/4952389.html
Copyright © 2011-2022 走看看