c# socket 多線程網絡通信,文件傳輸識別


總結:

          服務器端先創建一個socketwatch監控等待客戶端連接,客戶端連接后循環socketwatch.accept()創建多個通信線程,每個通信線程再創建新的數據處理線程,數據必須循環接收

            客戶端沒有socketwatch,直接創建socket,連接用connect(),發送用socket.send(),接收用receive(),數據也是循環接收的

 

 

 

 

一、服務器端單線程流程:    

            //服務器創建一個socket用於監聽
            Socket socketwatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //設置ip和端口
            IPAddress ip = IPAddress.Any;
            IPEndPoint endpoint = new IPEndPoint(ip, Convert.ToInt32(textBox2.Text));
            //綁定,即監聽
            socketwatch.Bind(endpoint);
            //設置監聽數量
            socketwatch.Listen(10);
            Msger("監聽成功!"+"\n\r");
            //等待客戶端連接,並創建一個負責通信的socket, 單線程的話會一直等待accept(),卡死
            Socket socketsend = socketwatch.Accept();
            //接收遠程連接的ip信息
            Msger(socketsend.RemoteEndPoint.ToString()+"  連接進來");

 服務器端多線程: 一個監聽socket可以創建多個通信socket,監聽socket循環創建多個通信socket線程,其中每個通信socket再創建一個線程處理信息,預防卡死

 

 

 

  private void button1_Click(object sender, EventArgs e)
        {
            //服務器創建一個socket用於監聽
            Socket socketwatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //設置ip和端口
            IPAddress ip = IPAddress.Any;
            IPEndPoint endpoint = new IPEndPoint(ip, Convert.ToInt32(textBox2.Text));
            //綁定,即監聽
            socketwatch.Bind(endpoint);
            //設置監聽數量
            socketwatch.Listen(10);
            Msger("監聽成功!" + "\n\r");
            //創建線程預防卡死
            Thread th = new Thread(Listen);
            th.IsBackground = true;
            th.Start(socketwatch);// 傳入監聽進程

        }

        //監聽socket循環創建多個通信socket線程,其中每個通信socket再創建一個線程處理信息,預防卡死
        
        private void Listen(object s)
        {
            //類型轉換,as轉換成功返回值否則NULL
            Socket socketwatch = s as Socket;
            //等待客戶端連接,並創建一個負責通信的socket

            while (true)
            {
               Socket socketsend = socketwatch.Accept();
               Msger(socketsend.RemoteEndPoint.ToString() + "  連接進來" + "\t\r\n");

             //創建一個新的線程處理客戶端發送過來的信息,否則一個socket就堵塞
                Thread th = new Thread(Operater);
                th.IsBackground = true;
                th.Start(socketsend);
               
            }

        }
        /// <summary>
        /// 信息處理線程
        /// </summary>
        /// <param name="s">socket返回客戶端信息</param>
        public void Operater(object s)
        {
            Socket socketsend = s as Socket;
            //必須循環接收消息
            while (true)
            {        
            //創建字節數組並接受傳過來的數據,返回int為實際使用值
            byte[] receive = new byte[1024 * 1024 * 2];
            int realr = socketsend.Receive(receive);
            //判斷客戶端發送的內容,如果為0則停止循環
            if (realr == 0)
            {
                break;
            }
            //解碼
            string text = Encoding.UTF8.GetString(receive, 0, realr);
            //寫入textbox
            Msger(text);
            }
        }

        public void Msger(string ms)
        {
            textBox3.AppendText(ms + "\n\r"); //追加方式

        }

二、客戶端簡單流程:  

 

 private void button4_Click(object sender, EventArgs e)
        {
            //創建socket
            socketcustomsend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //設置ip和port
            IPAddress ip = IPAddress.Parse(textBox5.Text);
            IPEndPoint ipendpoint = new IPEndPoint(ip, Convert.ToInt32(textBox6.Text));
            //連接
            socketcustomsend.Connect(ipendpoint);
            textBox4.Text = "連接成功!";


            //創建進程接受服務器傳來的信息
            Thread th = new Thread(CustomReceive);
            th.IsBackground = true;
            th.Start(socketcustomsend);

        }
        /// <summary>
        /// 循環接受服務器傳來的信息
        /// </summary>
        /// <param name="s">通信的socket</param>
        public void CustomReceive(object s)
        {
            while (true) //循環接收信息
            {
                Socket socketcustomsend = s as Socket;
                byte[] b = new byte[1024 * 1024 * 5];
                int r = socketcustomsend.Receive(b);
                if (r==0) //0表示服務器端關閉
                {
                    break;
                }
                textBox4.Text = Encoding.UTF8.GetString(b, 0, r);
                }
                

            }

  

三、通信的例子

using System;
using System.Collections;
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 socket通信
{
    public partial class socket練習 : Form
    {
        public socket練習()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            //服務器創建一個socket用於監聽
            Socket socketwatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //設置ip和端口
            IPAddress ip = IPAddress.Any;
            IPEndPoint endpoint = new IPEndPoint(ip, Convert.ToInt32(textBox2.Text));
            //綁定,即監聽
            socketwatch.Bind(endpoint);
            //設置監聽數量
            socketwatch.Listen(10);
            Msger("監聽成功!" + "\n\r");
            //創建線程預防卡死
            Thread th = new Thread(Listen);
            th.IsBackground = true;
            th.Start(socketwatch);// 傳入監聽進程

        }

        //監聽socket循環創建多個通信socket線程,其中每個通信socket再創建一個線程處理信息,預防卡死

        // 全局服務器端通信socket
        Socket socketsend;
        Dictionary<string, Socket> sdic = new Dictionary<string, Socket>();

        private void Listen(object s)
        {
            //類型轉換,as轉換成功返回值否則NULL
            Socket socketwatch = s as Socket;
            //等待客戶端連接,並創建一個負責通信的socket

            while (true)
            {
                socketsend = socketwatch.Accept();
                //將socket與ip信息放入字典集合
                sdic.Add(socketsend.RemoteEndPoint.ToString(), socketsend);
                //加入combox列表
                comboBox1.Items.Add(socketsend.RemoteEndPoint.ToString());
                //讓combox顯示當前連接的socket
                comboBox1.SelectedItem= socketsend.RemoteEndPoint.ToString();

                Msger(socketsend.RemoteEndPoint.ToString() + "  連接進來了" + "\t\r\n");

                //創建一個新的線程處理客戶端發送過來的信息,否則一個socket就堵塞
                Thread th = new Thread(Operater);
                th.IsBackground = true;
                th.Start(socketsend);

            }

        }
        /// <summary>
        /// 信息處理線程
        /// </summary>
        /// <param name="s">socket返回客戶端信息</param>
        public void Operater(object s)
        {
            Socket socketsend = s as Socket;
            //必須循環接收消息
            while (true)
            {
                //創建字節數組並接受傳過來的數據,返回int為實際使用值
                byte[] receive = new byte[1024 * 1024 * 10];
                int realr = socketsend.Receive(receive);
                //判斷客戶端發送的內容,如果為0則停止循環
                if (realr == 0)
                {
                    break;
                }
                //用文件頭判斷傳過來的是文字信息或文件的各種類型,0-文字信息 1-文件
                if (receive[0]==0) 
                {
                //解碼
                string text = Encoding.UTF8.GetString(receive, 1, realr-1);
                //寫入textbox
                Msger(text);

                }
                else if(receive[0]==1) //文件則保存
                {
                    SaveFileDialog sf = new SaveFileDialog();
                    sf.Filter = "所有文件|*.*";
                    sf.ShowDialog(this);         //注意this用法
                    using (FileStream fs=new FileStream(sf.FileName,FileMode.Create,FileAccess.Write))
                    {
                        fs.Write(receive, 1, realr-1); //-1去掉標志頭

                    }


                }

                
            }
        }

        public void Msger(string ms)
        {
            textBox3.AppendText(ms + "\n"); //追加方式

        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {

        }

        private void label5_Click(object sender, EventArgs e)
        {

        }

        private void label6_Click(object sender, EventArgs e)
        {

        }



        //客戶端socket
        Socket socketcustomsend;
        private void button4_Click(object sender, EventArgs e)
        {
            //創建socket
            socketcustomsend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //設置ip和port
            IPAddress ip = IPAddress.Parse(textBox5.Text);
            IPEndPoint ipendpoint = new IPEndPoint(ip, Convert.ToInt32(textBox6.Text));
            //連接
            socketcustomsend.Connect(ipendpoint);
            textBox4.Text = "連接成功!";


            //創建進程接受服務器傳來的信息
            Thread th = new Thread(CustomReceive);
            th.IsBackground = true;
            th.Start(socketcustomsend);

        }
        /// <summary>
        /// 循環接受服務器傳來的信息
        /// </summary>
        /// <param name="s">通信的socket</param>
        public void CustomReceive(object s)
        {
            while (true) //循環接收信息
            {
                Socket socketcustomsend = s as Socket;
                byte[] b = new byte[1024 * 1024 * 5];
                int r = socketcustomsend.Receive(b);
                if (r==0) //0表示服務器端關閉
                {
                    break;
                }
                textBox4.Text = Encoding.UTF8.GetString(b, 0, r);
                }
                

            }


        private void button2_Click(object sender, EventArgs e)
        {
            //准備數據
            byte[] b = Encoding.UTF8.GetBytes(textBox4.Text);
            //加入識別頭0
            List<byte> nb = new List<byte>();
            nb.Add(0);
            nb.AddRange(b);
           byte[] sb= nb.ToArray();

            //發送
            socketcustomsend.Send(sb);
        }

        private void button6_Click(object sender, EventArgs e)
        {
            textBox3.Clear();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            OpenFileDialog of = new OpenFileDialog();
            of.Multiselect = false;
            of.Filter = "所有文件|*.*";
            of.ShowDialog();
            textBox7.Text = of.FileName;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            using (FileStream fs = new FileStream(textBox7.Text, FileMode.Open, FileAccess.Read))
            {
                byte[] b = new byte[1024 * 1024 * 10];
                //返回真實使用數
                int r = fs.Read(b, 0, b.Length);

                //添加文件類型識別頭,list與array互相轉換
                List<byte> newbyte = new List<byte>();
                newbyte.Add(1);//1代表文件
                newbyte.AddRange(b);//將b中元素添加,add()為整個添加
                byte[] nb=newbyte.ToArray();

                //發送真實大小數據, 為r+1
                socketcustomsend.Send(nb,0,r+1,SocketFlags.None);

            }


        }

        private void button7_Click(object sender, EventArgs e)
        {
           sdic[comboBox1.SelectedItem.ToString()].Send(Encoding.UTF8.GetBytes(textBox3.Text));

        }
    }
}

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM