一蓑烟雨任余年 发表于 2020-3-12 15:15

【原创】C# Socket网络通信 基础代码 请求品鉴

话不多说 直接上图
服务端:


客户端:

客户端服务端执行文件(exe)
服务端关键代码
using System;using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
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;
using MyFunc;
namespace _10_13_Socket网络通信
{
    public partial class Form1 : Form
    {
      public Form1()
      {
            InitializeComponent();
      }

      private void Form1_Load(object sender, EventArgs e)
      {
            //获取本机ip
            
            txtIp.Text = "192.168.1.53";
            txtPoint.Text = "50000";
            //忽略线程检查
            Control.CheckForIllegalCrossThreadCalls = false;
      }
      Thread th;
      IPEndPoint point;
      private void BtnListen_Click(object sender, EventArgs e)
      {
            try
            {
                //创建侦听socket 采用Tcp stream流 IPV4协议
                Socket sktListen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //获取ip和端口号
               
                point = new IPEndPoint(IPAddress.Parse(txtIp.Text), Convert.ToInt32(txtPoint.Text));
                sktListen.Bind(point);//绑定通信信息(ip 和端口号)
                sktListen.Listen(10);//设置访问队列
                                     //由于侦听函数Accept()是一直在循环 如果用主进程调用此函数 程序会卡死 因此要创建新线程
                th = new Thread(Listen);
                th.IsBackground = true;
                th.Start(sktListen);
                Control.CheckForIllegalCrossThreadCalls = false;
            }
            catch
            {


            }

      }
      public void Listen(object o)
      {
            try
            {
                Socket newsktListen = o as Socket;//监听
                Socket socketLink;//监听数据
                newsktListen.Listen(10);
                while (true)//用死循环来无限等待客户端连接
                {

                  socketLink = newsktListen.Accept();//无限循环 直到接收到为止
                                                       //Accept结束 必定有客户端进入 这时就要给下拉框以及集合里添加数据了
                  GetReomtePoint(socketLink.RemoteEndPoint, socketLink);
                  txtMsg.AppendText(socketLink.RemoteEndPoint.ToString() + "链接成功\r\n");
                  Thread thMsg = new Thread(GetByte);
                  thMsg.Start(socketLink);

                }

            }
            catch (Exception)
            {

                throw;
            }





      }
      //客户连接成功之后 再创建一个线程来不断接收通讯信息
      public void GetByte(Object socketLink)
      {
            try
            {
                Socket newsocketLink = socketLink as Socket;
                //这个时候已经有客户端连接上了 写一个方法用来给下拉框赋值

                string str = "";
                while (true)
                {
                  byte[] buffer = new byte;
                  int r = newsocketLink.Receive(buffer);
                  str = newsocketLink.RemoteEndPoint.ToString() + "Say:" + System.Text.Encoding.Default.GetString(buffer, 0, r);
                  if (r == 0)
                  {
                        break;
                  }
                  txtMsg.AppendText(str + "\r\n");
                }
            }
            catch (Exception)
            {

                throw;
            }



      }
      Dictionary<string, Socket> infodic = new Dictionary<string, Socket>();
      int i = 0;
      /// <summary>
      /// 这个方法是给下拉框赋值 因为后期也要选择客户信息 跟选定的IP通信 因此要用集合记录下来ip 和跟ip通信的socket
      /// </summary>
      /// <param name="point"></param>
      /// <param name="newsocketLink"></param>
      public void GetReomtePoint(EndPoint point, Socket newsocketLink)
      {


            infodic.Add(point.ToString(), newsocketLink);
            cmbIPEndPoint.Items.Add(point);

            cmbIPEndPoint.SelectedIndex = i;
            i++;
      }

      private void Form1_FormClosing(object sender, FormClosingEventArgs e)
      {


      }

      private void BtnSend_Click(object sender, EventArgs e)
      {
            try
            {
                //插入0表示发送文本
               
                //发送txtsendmsg中的txt 并给字节数组的第一个索引插入0
                byte []bytedata = System.Text.Encoding.Default.GetBytes(txtSendMsg.Text);
                bytedata = MyFunc.ByteOperate.Insert(bytedata, 0, 0);
                Send(bytedata,txtSendMsg.Text);

            }
            catch (Exception)
            {

                throw;
            }
            //根据key寻找value

      }
      //写一个发送的方法
      public void Send(byte []buffer,string txt)
      {
            Socket newsocketLink = infodic;

            newsocketLink.Send(buffer);
            
            txtMsg.AppendText("Say:" + txt + "\r\n");
            //点击之后txtbox中的文本要清空
            txtSendMsg.Text = "";
      }
      OpenFileDialog ofd;
      private void BtnSendFile_Click(object sender, EventArgs e)
      {
            ofd = new OpenFileDialog();
            ofd.InitialDirectory = @"F:\PKX桌面";
            ofd.Title = "请选择要发送的文件";
            ofd.Filter = "图片文件|*.jpg|文本文件|*.txt|音乐文件|*.wav|视频文件|*.rmvb|所有文件|*.*";
            ofd.ShowDialog();
            string path = ofd.FileName;
            if (path=="")
            {
                return;
            }
            else
            {
                using (FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                  byte[] buffer = new byte;
                  fsRead.Read(buffer, 0, buffer.Length);
                  buffer = MyFunc.ByteOperate.Insert(buffer, 1, 0);//插入1 表示发送文件
                                                                     //发送文件
                  Send(buffer, "发送文件:" + path);
                }
            }
            
            
      }

      private void BtnShake_Click(object sender, EventArgs e)
      {
            byte[] buffer = new byte;
            buffer = MyFunc.ByteOperate.Insert(buffer, 2, 0);//字节用2表示
            Send(buffer,"给对方发送震动");
      }

      private void btnClose_Click(object sender, EventArgs e)
      {
            Process.GetCurrentProcess().Kill();
      }
    }
}

客户端关键代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
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;
using MyFunc;
namespace _10_14_Socket网络通信_客户端
{
    public partial class Form1 : Form
    {
      public Form1()
      {
            InitializeComponent();
      }
      Socket socClient;
      private void Form1_Load(object sender, EventArgs e)
      {
            Control.CheckForIllegalCrossThreadCalls = false;
            socClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);



      }

      private void BtnSend_Click(object sender, EventArgs e)
      {
            try
            {
                socClient.Send(System.Text.Encoding.Default.GetBytes(txtSend.Text));
                txtMsg.AppendText("Say:" + txtSend.Text + "\r\n");
                txtSend.Text = "";
            }
            catch (Exception)
            {

                throw;
            }


      }
      public void GetByte()
      {
            try
            {
                IPAddress ip = IPAddress.Parse("192.168.1.53"); //new IPAddress(System.Text.Encoding.Default.GetBytes("192.168.1.53"));
                socClient.Connect(ip,50000);
                button1.Hide();
                string str = "";
               
                while (true)//这里一定要死循环 循环接收 不能用socClient.Available != 0
                {

                  byte[] buffer = new byte;
                  int r = socClient.Receive(buffer);
                  //判断收到的字节的第一个下标的值
                  switch (buffer)
                  {
                        case 0://是文本
                            {
                              buffer = MyFunc.ByteOperate.Remove(buffer, 0);
                              str = socClient.RemoteEndPoint.ToString() + "Say:" + System.Text.Encoding.Default.GetString(buffer, 0, r);
                              if (r == 0)
                              {
                                    break;
                              }
                              txtMsg.AppendText(str + "\r\n");
                            }
                            break;
                        case 1://是文件
                            {
                              
                              buffer = MyFunc.ByteOperate.Remove(buffer, 0);//移除协议
                                                                              //接收到文件 需要打开保存窗口
                              SaveFileDialog sfd = new SaveFileDialog();
                              sfd.Title = "请选择要保存的文件路径和文件名称";
                              sfd.InitialDirectory = @"F:\PKX桌面";
                              sfd.ShowDialog(this);
                              if (sfd.FileName == "")
                              {
                                    return;
                              }
                              else
                              {
                                    using (FileStream fsWrite = new FileStream(sfd.FileName, FileMode.OpenOrCreate, FileAccess.Write))
                                    {
                                        fsWrite.Write(buffer, 0, buffer.Length);
                                    }
                                    MessageBox.Show("保存成功!");
                              }
                            }
                            break;
                        case 2://发送的是震动
                            {
                              this.Show();
                              for (int i = 0; i < 500; i++)
                              {
                                    //this.Location = new Point(220,300);
                                    //this.Location = new Point(230, 310);
                                    //this.Location.X = this.Location.X + 50;
                                    this.Location = new Point(this.Location.X + 10, this.Location.Y + 10);
                                    this.Location = new Point(this.Location.X - 10, this.Location.Y - 10);
                              }
                              

                            }
                            break;
                        default:
                            break;
                  }




                }
            }
            catch (Exception)
            {

                throw;
            }

      }

      private void Button1_Click(object sender, EventArgs e)
      {


            Thread th = new Thread(GetByte);
            th.IsBackground = true;
            th.Start();
            Control.CheckForIllegalCrossThreadCalls = false;

      }

      private void BtnShake_Click(object sender, EventArgs e)
      {

      }

      private void btnClose_Click(object sender, EventArgs e)
      {
            Process.GetCurrentProcess().Kill();
      }
    }
}




一蓑烟雨任余年 发表于 2020-3-12 15:44

对了 命名空间里using MyFunc 主要是引用了我自己写的字节操作的函数
因为如果客户发送图片 文字 或者震动的时候 接收方无法判断 需要在发送前插入一个字节 让接收方来判断接收到的是什么
具体实现代码如下:
public static class ByteOperate
    {
      /// <summary>
      /// 给自己数组插入指定的字节
      /// </summary>
      /// <param name="oldbyte">原字节数组</param>
      /// <param name="insertbyet">要插入的字节</param>
      /// <param name="index">要插入的索引</param>
      /// <returns></returns>
      public static byte[] Insert(byte []oldbyte,byte insertbyet,int index)
      {
            List<byte> list = new List<byte>();
            list = oldbyte.ToList();
            list.Insert(index, insertbyet);
            return list.ToArray();
      }
      /// <summary>
      /// 移除数组中的某个下标的元素
      /// </summary>
      /// <param name="oldbyte">元素组</param>
      /// <param name="index">要移除的某个下标</param>
      /// <returns>移除某个元素后的数组</returns>
      public static byte[] Remove(byte[] oldbyte, int index)
      {
            List<byte> list = new List<byte>();
            list = oldbyte.ToList();
            list.RemoveAt(index);
            return list.ToArray();
      }
    }
页: [1]
查看完整版本: 【原创】C# Socket网络通信 基础代码 请求品鉴