C# socket 多线程网络编程winform文件传输

目录

 

服务器端

客户端

源代码下载


服务器端

可以连接多个客户端,接受客户端的文本信息,并对文本信息进行广播。

可以发送文本和文件给客户端,也是广播的新式发送,就是每个客户端都能收到就叫广播。

服务器中需要两个socket,一个是服务器,另一个是连接进来的客户端socket

因为要连接进来很多socket,所以把服务器中连接进来的客户端单独封装成一个类

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace TCP服务器端
{
    class Client
    {
        private Socket clientSocket;
        public  Thread t;
        private byte[] data = new byte[1024];//这个是一个数据容器
        public   string acceptmessage="";
   
        public Client(Socket s)
        {
            clientSocket = s;
            //启动一个线程 处理客户端的数据接收
            t = new Thread(ReceiveMessage);
            t.Start();
        }
        public void ReceiveMessage()
        {
            //一直接收客户端的数据
            while (true)
            {
                try
                {
                    //在接收数据之前  判断一下socket连接是否断开
                    int length = clientSocket.Receive(data);
                    if (length == 0)//客户端断开连接
                    {
                        break;
                    }
                    string message = Encoding.UTF8.GetString(data, 0, length);
                    message = clientSocket.RemoteEndPoint.ToString() + ":" + message ;
                    //接收到数据的时候 要把这个数据 分发到客户端
                    //广播这个消息
                    Form1.BroadcastMessage(message);
                    Form1.mainform.textBox3.AppendText(message + "\n");
                }
                catch { }
  
            }
        }
        //服务器发送消息给客户端
        public void SendMessage(string message)
        {
            byte[] data = Encoding.UTF8.GetBytes(message);
            clientSocket.Send(data);
        }


        public bool Connected
        {
            get { return clientSocket.Connected; }
        }
    }
}

主窗口代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace TCP服务器端
{
    public partial class Form1 : Form
    {
        static List<Client> clientList = new List<Client>(); //管理客户端套接字列表
        Thread t;
        Socket tcpServer;
        public static Form1 mainform; //主窗口对象
        public Form1()
        {
            //在窗口加载的时候取消线程的检查
            Control.CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
            this.textBox1.Text = "192.168.6.21";
            mainform = this;
        }
        //将收到的消息广播
        public static void BroadcastMessage(string message)
        {
            var notConnectedList = new List<Client>();//存放断开的客户端
            foreach (var client in clientList)
            {
                if (client.Connected)
                    client.SendMessage(message);//服务器向客户端发送消息
                else//有断开的客户端就存放进列表
                {
                    notConnectedList.Add(client);
                }
            }//将断开的客户端删掉
            foreach (var temp in notConnectedList)
            {
                clientList.Remove(temp);
            }           
        }
        //打开服务器
        private void button2_Click(object sender, EventArgs e)
        {
            tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            tcpServer.Bind(new IPEndPoint(IPAddress.Parse(textBox1.Text), Convert.ToInt32(textBox2.Text)));
            textBox3.AppendText("服务器打开成功\n");
            tcpServer.Listen(100);
            t = new Thread(checkconnect);//开启线程来监听客户端的连接
            t.Start();
        }
        //发送消息按钮
        private void button1_Click(object sender, EventArgs e)
        {
            BroadcastMessage("服务器:"+textBox4.Text);//将消息广播出去
            if (clientList.Count == 0)
            {
                textBox3.AppendText("发送失败,无客户端连接");
            }
            else
            {
                textBox3.AppendText(textBox4.Text + "\n");
            }
            
        }
        private void checkconnect()
        {
            try
            {
                while (true)
                {

                    Socket clientSocket = tcpServer.Accept();
                    textBox3.AppendText("a client is connected !" + "\n");
                    Client client = new Client(clientSocket);//把与每个客户端通信的逻辑(收发消息)放到client类里面进行处理
                    clientList.Add(client);
                }
            }
            catch 
            { }

        }
        //关闭窗口,杀死所有线程
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            System.Diagnostics.Process.GetCurrentProcess().Kill();
        }

        //选择文件
        private void button3_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = @"C:\Users\SpringRain\Desktop";
            ofd.Title = "请选择要发送的文件";
            ofd.Filter = "文本文件|*.txt|音乐文件|*.wav|图片文件|*.jpg|所有文件|*.*";
            ofd.ShowDialog();
            //获得选中文件的路径
            string path = ofd.FileName;
            textBox5.Text = path;
        }

        //发送文件按钮
        private void button4_Click(object sender, EventArgs e)
        {
            using (FileStream fsRead = new FileStream(textBox5.Text, FileMode.Open, FileAccess.Read))
            {
                byte[] buffer = new byte[fsRead.Length];
                //实际读取到的有效字节数
                int r = fsRead.Read(buffer, 0, buffer.Length);
                //在读取到的字节数组前加一个0作为发送的是文件的标志位
                List<byte> list = new List<byte>();
                list.Add(1);
                list.AddRange(buffer);
                byte[] newBuffer = list.ToArray();
                //广播发送
                //这里又转成了字符串,主要是因为广播函数的传入参数写死了
                //建议单独写一个广播文件的函数,直接传入字节数组
                string message = Encoding.UTF8.GetString(newBuffer, 0, r+1);
                BroadcastMessage(message);
            }
        }
    }
}

客户端

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace TCP客户端
{
    public partial class Form1 : Form
    {
        public Socket tcpClient;
        byte[] data = new byte[1024 * 1024 * 5];//5M大
        public Form1()
        {
            //在窗口加载的时候取消线程的检查
            Control.CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
            this.textBox1.Text = "192.168.6.21";
            tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        }

        //连接
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                IPAddress ipaddress = IPAddress.Parse(textBox1.Text);//可以把一个字符串的ip地址转化成一个ipaddress的对象
                EndPoint point = new IPEndPoint(ipaddress, Convert.ToInt32(textBox2.Text));
                tcpClient.Connect(point);//通过ip:端口号 定位一个要连接到的服务器端
                tcpClient.Send(Encoding.UTF8.GetBytes("客户端连接成功"));
                textBox3.AppendText("连接成功");
                Thread t = new Thread(ReceiveMessage);
                t.Start();
            }
            catch 
            {}
        }
        //发送
        private void button2_Click(object sender, EventArgs e)
        {
            //向服务器端发送消息
            try
            {
                string message2 = textBox4.Text;
                tcpClient.Send(Encoding.UTF8.GetBytes(message2));//把字符串转化成字节数组,然后发送到服务器端 
            }
            catch
            {}
            
        }
        private void ReceiveMessage()
        {
            try
            {
                //一直接收服务端的数据
                while (true)
                {
                    if (tcpClient.Connected == false)
                    {
                        break;
                    }
                    else
                    {
                        int length = tcpClient.Receive(data);
                        if (data[0] == 1)//接受文件
                        {
                            SaveFileDialog sfd = new SaveFileDialog();
                            sfd.InitialDirectory = @"C:\Users\SpringRain\Desktop";
                            sfd.Filter = "文本文件|*.txt|音乐文件|*.wav|图片文件|*.jpg|所有文件|*.*";
                            sfd.Title = "请选择要保存的文件路径";
                            sfd.ShowDialog(this);
                            string path = sfd.FileName;
                            using (FileStream fsWrite = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
                            {
                                fsWrite.Write(data, 1, length - 1);
                            }
                            MessageBox.Show("保存成功");
                        }
                        else//接受文本
                        {
                            string message = Encoding.UTF8.GetString(data, 0, length);
                            string time = DateTime.Now.ToString();
                            textBox3.AppendText(time + "--" + message + "\n");
                        }
                    }
                }
            }
            catch
            { }
        }

        //窗体关闭,杀死所有线程
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            System.Diagnostics.Process.GetCurrentProcess().Kill();
            tcpClient.Close();
        }
    }
}

源代码下载

链接:https://pan.baidu.com/s/1i2sYJyKei-yYrcR2eIKUkQ 
提取码:yqp7 

如有帮助,请点赞。谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猪猪派对

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值