C# Socket 实现服务端和客户端通信

2022/8/4 14:25:22

本文主要是介绍C# Socket 实现服务端和客户端通信,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

C#里面封装好了Socket,直接引用即可使用

关键字:using System.Net; using.System.Sockets;

创建一个负责监听的Socket:Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 第一个参数是IPV42,第二个为流式,TCP用流式,UDP用数式,第三个为协议类型

IP地址获取:IPAddress ip = IPAddress.Any; Any是指当前服务器的所有ip

端口获取:IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));这里获取的文本框里的端口。

将负责监听的Socket绑定IP地址和端口:socketWatch.Bind(point);

设置监听队列,某一时间段最大连接数:socketWatch.Listen(100);

这样一个Socket就创建好了。

下面是接受连接:

    //负责监听的Socket来接收客户端的连接
    while (true)
    {
        //负责跟客户端通信的Socket
        socketSend = socketWatch.Accept();
        //将远程连接的客户端的IP和Socket存入集合中
        dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
        //将远程连接的客户端的IP地址和端口号存储到下拉框中
        this.Invoke(new Action(addCbomDic));
                
        //连接成功
        this.Invoke(new Action<string>(ShowMsg), socketSend.RemoteEndPoint.ToString() + "连接成功");
        // ShowMsg(socketSend.RemoteEndPoint.ToString() + "连接成功");

        //接收客户端消息线程
        Task.Run(() => Recive(socketSend));
            
    }

 以上就是Socket部分的主要代码了,下面是服务端的主要实现代码

服务端主要逻辑代码
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.Tasks;
using System.Windows.Forms;
using System.IO;

namespace MonitorTest
{
    public partial class Form1 : Form
    {
        Socket socketSend;
        //将远程客户端的IP地址和Socket存入集合中
        Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
        public Form1()
        {
            InitializeComponent();
        }

        private void btnsStart_Click(object sender, EventArgs e)
        {
            //创建一个负责监听得Socket
            //第一个参数是IPV42,第二个为流式,TCP用流式,UDP用数式,第三个为协议类型
            Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //创建IP地址和端口号对象
            IPAddress ip = IPAddress.Any;   //IPAddress.Parse(txtServer.Text);
            IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));

            //让负责监听的Socket绑定IP地址跟端口号
            socketWatch.Bind(point);

            ShowMsg("监听成功");

            //设置监听队列,某一时间点能够连入客户端的最大数量+
            socketWatch.Listen(100);
            Task.Run(()=>Listen(socketWatch));            
        }

        /// <summary>
        /// 等待客户端的连接,并且创建一个负责通信的Socket
        /// </summary>
        void Listen(Socket socketWatch)
        {
            //负责监听的Socket来接收客户端的连接
            while (true)
            {
                //负责跟客户端通信的Socket
                socketSend = socketWatch.Accept();
                //将远程连接的客户端的IP和Socket存入集合中
                dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
                //将远程连接的客户端的IP地址和端口号存储到下拉框中
                this.Invoke(new Action(addCbomDic));
                
                //连接成功
                this.Invoke(new Action<string>(ShowMsg), socketSend.RemoteEndPoint.ToString() + "连接成功");
                // ShowMsg(socketSend.RemoteEndPoint.ToString() + "连接成功");

                //接收客户端消息线程
                Task.Run(() => Recive(socketSend));
            
            }
            
        }

        /// <summary>
        /// 将数据添加到下拉列表中
        /// </summary>
        void addCbomDic()
        {
            cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString());
        }
        
        /// <summary>
        /// 接受客户端发来的消息
        /// </summary>
        /// <param name="socketSend"></param>
        void Recive(Socket socketSend)
        {
            while (true)
            {
                try
                {
                    //客户端连接成功后,服务器应该接受客户端发来的消息
                    byte[] buffer = new byte[1024 * 1024 * 4];
                    //实际接收到的有效字节数
                    int r = socketSend.Receive(buffer);
                    if (r == 0)
                    {
                        break;
                    }
                    string str = Encoding.UTF8.GetString(buffer, 0, r);
                    this.Invoke(new Action<string>(ShowMsg), socketSend.RemoteEndPoint.ToString() + " : " + str);
                }
                catch
                {   }
            }
        }

        void ShowMsg(string str)
        {
            txtLog.AppendText(str + "\r\n");
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //关闭检查,允许子线程访问主线程
            //Control.CheckForIllegalCrossThreadCalls = false;
        }

        /// <summary>
        /// 服务器给客户端发送消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSend_Click(object sender, EventArgs e)
        {
            string str = txtMsg.Text;
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
            List<byte> list = new List<byte>();
            list.Add(0);
            list.AddRange(buffer);

            byte[] newBuffer = list.ToArray();
            try
            {

                //获得用户在下拉框中选中的IP地址
                string ip = cboUsers.SelectedItem.ToString();
                dicSocket[ip].Send(newBuffer);
                ShowMsg(str);
            }
            catch { }
            


            //  socketSend.Send(newBuffer);
        }

        /// <summary>
        /// 选择要发送的文件 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSelect_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = @"D:\Document\Test";
            ofd.Title = "请选择要发送的文件";
            ofd.Filter = "所有文件|*.*";
            ofd.ShowDialog();

            txtPath.Text = ofd.FileName;
        }

        private void btnSendFile_Click(object sender, EventArgs e)
        {
            //获得要发送文件的路径
            string path = txtPath.Text;
            using (FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                byte[] buffer = new byte[1024 * 1024 * 8];
                int r = fsRead.Read(buffer,0,buffer.Length);
                List<byte> list = new List<byte>();
                list.Add(1);
                list.AddRange(buffer);
                byte[] newBuffer = list.ToArray();
                dicSocket[cboUsers.SelectedItem.ToString()].Send(newBuffer, 0, r+1, SocketFlags.None);
            }
        }

        /// <summary>
        /// 发送震动    
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnShake_Click(object sender, EventArgs e)
        {
            byte[] buffer = new byte[1];
            buffer[0] = 2;
            dicSocket[cboUsers.SelectedItem.ToString()].Send(buffer);
        }
    }
}

 

客户端主要代码:

客户端主要逻辑代码
 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.Tasks;
using System.Windows.Forms;

namespace ClientSimple
{
    public partial class Form1 : Form
    {
        Socket socketSend;
        public Form1()
        {
            InitializeComponent();
        }

        private void btnsStart_Click(object sender, EventArgs e)
        {
            try
            {
                //创建负责通信的Socket
                socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ip = IPAddress.Parse(txtServer.Text.Trim());
                IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text.Trim()));

                //获得要链接的远程服务器应用程序的IP地址和端口号
                socketSend.Connect(point);

                ShowMsg("连接成功");
                Task.Run(() => Recive());
            }
            catch 
            { }
        }

        /// <summary>
        /// 不停的接受服务器发来的消息
        /// </summary>
        void Recive()
        {
            while (true)
            {
                try
                {
                    //客户端连接成功后,服务器应该接受客户端发来的消息
                    byte[] buffer = new byte[1024 * 1024 * 4];
                    int r = socketSend.Receive(buffer);
                    //实际接收到的有效字节数
                    if (r == 0)
                    {
                        break;
                    }
                    if (buffer[0] == 0)
                    {
                        string str = Encoding.UTF8.GetString(buffer, 1, r-1);
                        this.Invoke(new Action<string>(ShowMsg), socketSend.RemoteEndPoint.ToString() + " : " + str);
                    }
                    else if (buffer[0] == 1)
                    {
                        this.Invoke(new Action<byte[], int>(SaveFile), buffer, r);
                    }
                    else if (buffer[0] == 2)
                    {
                        this.Invoke(new Action(Shake));
                    }
                }
                catch
                { }
            }
        }

        /// <summary>
        /// 震动
        /// </summary>
        void Shake()
        {
            for (int i = 0; i < 500; i++)
            {
                this.Location = new Point(200, 200);
                this.Location = new Point(280, 280);
            }
        }

        /// <summary>
        /// 存储文件
        /// </summary>
        void SaveFile(byte[] buffer,int r)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.InitialDirectory = @"D:\Document\Test";
            sfd.Title = "请选择要保存到路径";
            sfd.Filter = "所有文件|*.*";

            sfd.ShowDialog(this);
            string path = sfd.FileName;
            using (FileStream fsWrite = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
            {
                fsWrite.Write(buffer, 1, r - 1);
            }
            MessageBox.Show("保存成功");
        }

        void ShowMsg(string str)
        {
            txtLog.AppendText(str + "\r\n");
        }
        /// <summary>
        /// 客户端给服务器发送消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSend_Click(object sender, EventArgs e)
        {
            string str = txtMsg.Text.Trim();
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
            ShowMsg(str);
            socketSend.Send(buffer);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //Control.CheckForIllegalCrossThreadCalls = false;
        }
    }
}

 

实现效果图:

总结:创建Socket过程,发送数据socket.Send()方法。接收数据socket.Receive()。

这个demo还非常简陋,有很多地方没有完善。主要目的Socket学习,所以很多能看见的Bug就没处理。客户端连接成功后,服务端要选择下拉列表中的客户端才能发信息,不然直接发就报错了。文件发送也不能为空,接收文件也不能取消,接收文件也不知道文件的后缀(类型)。。。。。。



这篇关于C# Socket 实现服务端和客户端通信的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程