C# Socket异步实现消息发送--附带源码
前言
看了一百遍,不如动手写一遍。
Socket这块使用不是特别熟悉,之前实现是公司有对应源码改改能用。
但是不理解实现的过程和步骤,然后最近有时间自己写个demo实现看看,熟悉熟悉Socket。
网上也有好的文章,结合别人的理接和自己实践总算写完了。。。
参考:https://www.cnblogs.com/sunev/实现
参考:https://blog.csdn.net/woshiyuanlei/article/details/47684221
https://www.cnblogs.com/dotnet261010/p/6211900.html
理解握手过程,关闭时的握手过程(关闭的过程弄了半天,总算弄懂了意思)。
实现过程
总体包含:开启,关闭,断线重连(客户端),内容发送。
说明:服务端和客户端代码基本一致,客户端需要实时监听服务端状态,断开时需要重连。
页面效果图:
服务端实现(实现不包含UI部分 最后面放所有代码和下载地址)
给出一个指定的地址IP+Port,套接字类型初始化Socket
使用Bind方法进行关联,Listen(10) 注释: 挂起连接队列的最大长度。我的通俗理接:你有一个女朋友这时你不能找别的,但是如果分手了就可以找别的,
BeginAccept包含一个异步的回调,获取请求的Socket
var s_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); s_socket.Bind(new IPEndPoint(IPAddress.Parse(ip), port)); s_socket.Listen();//同时连接的最大连接数 s_socket.BeginAccept(new AsyncCallback(Accept), s_socket);//获取连接
ClientState,自己声明的一个类用于接收数据(对应ReadCallback)和内部处理
Accept异步请求回调,当有Socket请求时会进去该回调,
EndAccept,我的理接为给当前Socket创建一个新的链接释放掉 Listen
BeginReceive,包含一个消息回调(ReadCallback),只需给出指定长度数组接收Socket上传的消息数据
BeginAccept,再次执行等待方法等待后续Socket连接
/// <summary> /// 异步连接回调 获取请求Socket /// </summary> /// <param name="ar">请求的Socket</param> private void Accept(IAsyncResult ar) { try { //获取连接Socket 创建新的连接 Socket myServer = ar.AsyncState as Socket; Socket service = myServer.EndAccept(ar); ClientState obj = new ClientState(); obj.clientSocket = service; //接收连接Socket数据 service.BeginReceive(obj.buffer, , ClientState.bufsize, SocketFlags.None, new AsyncCallback(ReadCallback), obj); myServer.BeginAccept(new AsyncCallback(Accept), myServer);//等待下一个连接 } catch (Exception ex) { Console.WriteLine("服务端关闭"+ex.Message+" "+ex.StackTrace); } }
EndReceive,通俗理接买东西的时候老板已经打包好了,付钱走人。
BeginReceive,当数据处理完成之后,和Socket连接一样需再次执行获取下次数据
/// <summary> /// 数据接收 /// </summary> /// <param name="ar">请求的Socket</param> private void ReadCallback(IAsyncResult ar) { //获取并保存 ClientState obj = ar.AsyncState as ClientState; Socket c_socket = obj.clientSocket; int bytes = c_socket.EndReceive(ar); //接收完成 重新给出buffer接收 obj.buffer = new byte[ClientState.bufsize]; c_socket.BeginReceive(obj.buffer, , ClientState.bufsize, , new AsyncCallback(ReadCallback), obj); }
Send,消息发送比较简单,将发送的数组转成数组的形式进行发送
/// <summary> /// 发送消息 /// </summary> /// <param name="c_socket">指定客户端socket</param> /// <param name="by">内容数组</param> private void Send(Socket c_socket, byte[] by) { //发送 c_socket.BeginSend(by, , by.Length, SocketFlags.None, asyncResult => { try { //完成消息发送 int len = c_socket.EndSend(asyncResult); } catch (Exception ex) { Console.WriteLine("error ex=" + ex.Message + " " + ex.StackTrace); } }, null); }
客户端实现(实现不包含UI部分 最后面放所有代码和下载地址)
相对于服务端差别不大,只是需要在链接之后增加一个监听机制,进行断线重连,我写的这个比较粗糙。
BeginConnect,使用指定的地址ip+port进新一个异步的链接
Connect,链接回调
ConnectionResult,初始值为-2 在消息接收(可检测服务端断开),链接(链接失败)重新赋值然后判断是否为错误码然后重连
/// <summary> /// 连接Socket /// </summary> public void Start() { try { var endPoint = new IPEndPoint(IPAddress.Parse(ip), port); c_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); c_socket.BeginConnect(endPoint, new AsyncCallback(Connect), c_socket);//链接服务端 th_socket = new Thread(MonitorSocker);//监听线程 th_socket.IsBackground = true; th_socket.Start(); } catch (SocketException ex) { Console.WriteLine("error ex=" + ex.Message + " " + ex.StackTrace); } } //监听Socket void MonitorSocker() { while (true) { && ConnectionResult != -)//通过错误码判断 { Start(); } Thread.Sleep(); } }
Connec链接部分
/// <summary> /// 连接服务端 /// </summary> /// <param name="ar"></param> private void Connect(IAsyncResult ar) { try { ServiceState obj = new ServiceState(); Socket client = ar.AsyncState as Socket; obj.serviceSocket = client; //获取服务端信息 client.EndConnect(ar); //接收连接Socket数据 client.BeginReceive(obj.buffer, , ServiceState.bufsize, SocketFlags.None, new AsyncCallback(ReadCallback), obj); catch (SocketException ex) { ConnectionResult = ex.ErrorCode; Console.WriteLine(ex.Message + " " + ex.StackTrace); } }
整体数据发送和实现部分
声明一个指定的类,给出指定的标识,方便数据处理,
在发送文字消息,图片消息,震动时需要对应的判断其实最简便的方法是直接发送一个XML报文过去直接解析,
也可以采用在头部信息里面直接给出传送类型。
数组中给出了一个0-15的信息头
0-3 标识码,确认身份
4-7 总长度,总体长度可用于接收时判断所需长度
8-11 内容长度,判断内容是否接收完成
12-15 补0,1111(震动) 2222(图片数据,图片这块为了接收图片名称所以采用XML报文形式发送)
16开始为内容
/// <summary> /// 0-3 标识码 4-7 总长度 8-11 内容长度 12-15补0 16开始为内容 /// </summary> public class SendSocket { /// <summary> /// 头 标识8888 /// </summary> ] { 0x08, 0x08, 0x08, 0x08 }; /// <summary> /// 文本消息 /// </summary> public string Message; /// <summary> /// 是否发送震动 /// </summary> public bool SendShake = false; /// <summary> /// 是否发送图片 /// </summary> public bool SendImg = false; /// <summary> /// 图片名称 /// </summary> public string ImgName; /// <summary> /// 图片数据 /// </summary> public string ImgBase64; /// <summary> /// 组成特定格式的byte数据 /// 12-15 为指定发送内容 1111(震动) 2222(图片数据) /// </summary> /// <returns>特定格式的byte</returns> public byte[] ToArray() { if (SendImg)//是否发送图片 { //组成XML接收 可以接收相关图片数据 StringBuilder xmlResult = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); xmlResult.Append("<ImgMessage>"); xmlResult.AppendFormat("<ImgName>{0}</ImgName>", ImgName); xmlResult.AppendFormat("<ImgBase64>{0}</ImgBase64>", ImgBase64); xmlResult.Append("</ImgMessage>"); Message = xmlResult.ToString(); } byte[] byteData = Encoding.UTF8.GetBytes(Message);//内容 + byteData.Length;//总长度 byte[] SendBy = new byte[count]; Array.Copy(Header, , SendBy, , Header.Length);//添加头 byte[] CountBy = BitConverter.GetBytes(count); Array.Copy(CountBy, , SendBy, , CountBy.Length);//总长度 byte[] ContentBy = BitConverter.GetBytes(byteData.Length); Array.Copy(ContentBy, , SendBy, , ContentBy.Length);//内容长度 if (SendShake)//发动震动 { ] { , , , }; Array.Copy(shakeBy, , SendBy, , shakeBy.Length);//震动 } if (SendImg)//发送图片 { ] { , , , }; Array.Copy(imgBy, , SendBy, , imgBy.Length);//图片 } Array.Copy(byteData, , SendBy, , byteData.Length);//内容 return SendBy; } }
代码:
服务端:
窗体(UI)代码:
namespace SocketService { partial class Form1 { /// <summary> /// 必需的设计器变量。 /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 清理所有正在使用的资源。 /// </summary> /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows 窗体设计器生成的代码 /// <summary> /// 设计器支持所需的方法 - 不要修改 /// 使用代码编辑器修改此方法的内容。 /// </summary> private void InitializeComponent() { this.label1 = new System.Windows.Forms.Label(); this.txt_ip = new System.Windows.Forms.TextBox(); this.txt_port = new System.Windows.Forms.TextBox(); this.label2 = new System.Windows.Forms.Label(); this.btn_StartSocket = new System.Windows.Forms.Button(); this.txt_Monitor = new System.Windows.Forms.TextBox(); this.label3 = new System.Windows.Forms.Label(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.btn_SendImg = new System.Windows.Forms.Button(); this.btn_SendShake = new System.Windows.Forms.Button(); this.btn_SendMes = new System.Windows.Forms.Button(); this.txt_Mes = new System.Windows.Forms.TextBox(); this.label4 = new System.Windows.Forms.Label(); this.dataGridView1 = new System.Windows.Forms.DataGridView(); this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.Column2 = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.lab_ImgName = new System.Windows.Forms.Label(); this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.listBox_Mes = new System.Windows.Forms.ListBox(); this.listBox_attribute = new System.Windows.Forms.ListBox(); this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); this.btn_Stop = new System.Windows.Forms.Button(); this.label5 = new System.Windows.Forms.Label(); this.label6 = new System.Windows.Forms.Label(); this.label7 = new System.Windows.Forms.Label(); this.groupBox1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); this.groupBox2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; , ); this.label1.Name = "label1"; , ); ; this.label1.Text = "IP"; // // txt_ip // , ); this.txt_ip.Name = "txt_ip"; , ); ; this.txt_ip.Text = "127.0.0.1"; // // txt_port // , ); this.txt_port.Name = "txt_port"; , ); ; "; // // label2 // this.label2.AutoSize = true; , ); this.label2.Name = "label2"; , ); ; this.label2.Text = "端口"; // // btn_StartSocket // , ); this.btn_StartSocket.Name = "btn_StartSocket"; , ); ; this.btn_StartSocket.Text = "开始监听"; this.btn_StartSocket.UseVisualStyleBackColor = true; this.btn_StartSocket.Click += new System.EventHandler(this.btn_StartSocket_Click); // // txt_Monitor // , ); this.txt_Monitor.Name = "txt_Monitor"; this.txt_Monitor.ReadOnly = true; , ); ; // // label3 // this.label3.AutoSize = true; , ); this.label3.Name = "label3"; , ); ; this.label3.Text = "正在监听"; // // groupBox1 // this.groupBox1.Controls.Add(this.btn_SendImg); this.groupBox1.Controls.Add(this.btn_SendShake); this.groupBox1.Controls.Add(this.btn_SendMes); this.groupBox1.Controls.Add(this.txt_Mes); this.groupBox1.Controls.Add(this.label4); this.groupBox1.Controls.Add(this.dataGridView1); , ); this.groupBox1.Name = "groupBox1"; , ); ; this.groupBox1.TabStop = false; this.groupBox1.Text = "客户端连接列表"; // // btn_SendImg // , ); this.btn_SendImg.Name = "btn_SendImg"; , ); ; this.btn_SendImg.Text = "发送图片"; this.btn_SendImg.UseVisualStyleBackColor = true; this.btn_SendImg.Click += new System.EventHandler(this.btn_SendImg_Click); // // btn_SendShake // , ); this.btn_SendShake.Name = "btn_SendShake"; , ); ; this.btn_SendShake.Text = "发送震动"; this.btn_SendShake.UseVisualStyleBackColor = true; this.btn_SendShake.Click += new System.EventHandler(this.btn_SendShake_Click); // // btn_SendMes // , ); this.btn_SendMes.Name = "btn_SendMes"; , ); ; this.btn_SendMes.Text = "发送"; this.btn_SendMes.UseVisualStyleBackColor = true; this.btn_SendMes.Click += new System.EventHandler(this.btn_SendMes_Click); // // txt_Mes // , ); this.txt_Mes.Multiline = true; this.txt_Mes.Name = "txt_Mes"; , ); ; // // label4 // this.label4.AutoSize = true; , ); this.label4.Name = "label4"; , ); ; this.label4.Text = "消息输入"; // // dataGridView1 // this.dataGridView1.AllowUserToOrderColumns = true; this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { this.Column1, this.Column2}); , ); this.dataGridView1.Name = "dataGridView1"; ; , ); ; // // Column1 // this.Column1.HeaderText = "IP"; this.Column1.Name = "Column1"; // // Column2 // this.Column2.HeaderText = "Port"; this.Column2.Name = "Column2"; // // groupBox2 // this.groupBox2.Controls.Add(this.label7); this.groupBox2.Controls.Add(this.label6); this.groupBox2.Controls.Add(this.label5); this.groupBox2.Controls.Add(this.lab_ImgName); this.groupBox2.Controls.Add(this.pictureBox1); this.groupBox2.Controls.Add(this.listBox_Mes); this.groupBox2.Controls.Add(this.listBox_attribute); , ); this.groupBox2.Name = "groupBox2"; , ); ; this.groupBox2.TabStop = false; this.groupBox2.Text = "接收客户端消息"; // // lab_ImgName // this.lab_ImgName.AutoSize = true; , ); this.lab_ImgName.Name = "lab_ImgName"; , ); ; // // pictureBox1 // , ); this.pictureBox1.Name = "pictureBox1"; , ); this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; ; this.pictureBox1.TabStop = false; // // listBox_Mes // this.listBox_Mes.FormattingEnabled = true; ; , ); this.listBox_Mes.Name = "listBox_Mes"; , ); ; // // listBox_attribute // this.listBox_attribute.FormattingEnabled = true; ; , ); this.listBox_attribute.Name = "listBox_attribute"; , ); ; // // openFileDialog1 // this.openFileDialog1.FileName = "openFileDialog1"; // // btn_Stop // , ); this.btn_Stop.Name = "btn_Stop"; , ); ; this.btn_Stop.Text = "关闭监听"; this.btn_Stop.UseVisualStyleBackColor = true; this.btn_Stop.Click += new System.EventHandler(this.btn_Stop_Click); // // label5 // this.label5.AutoSize = true; , ); this.label5.Name = "label5"; , ); ; this.label5.Text = "接收消息显示"; // // label6 // this.label6.AutoSize = true; , ); this.label6.Name = "label6"; , ); ; this.label6.Text = "接收图片显示"; // // label7 // this.label7.AutoSize = true; , ); this.label7.Name = "label7"; , ); ; this.label7.Text = "数据显示"; // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; , ); this.Controls.Add(this.btn_Stop); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); this.Controls.Add(this.txt_Monitor); this.Controls.Add(this.label3); this.Controls.Add(this.btn_StartSocket); this.Controls.Add(this.txt_port); this.Controls.Add(this.label2); this.Controls.Add(this.txt_ip); this.Controls.Add(this.label1); this.Name = "Form1"; this.Text = "服务端"; this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); this.groupBox2.ResumeLayout(false); this.groupBox2.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Label label1; private System.Windows.Forms.TextBox txt_ip; private System.Windows.Forms.TextBox txt_port; private System.Windows.Forms.Label label2; private System.Windows.Forms.Button btn_StartSocket; private System.Windows.Forms.TextBox txt_Monitor; private System.Windows.Forms.Label label3; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.Button btn_SendShake; private System.Windows.Forms.Button btn_SendMes; private System.Windows.Forms.TextBox txt_Mes; private System.Windows.Forms.Label label4; private System.Windows.Forms.DataGridView dataGridView1; private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.ListBox listBox_attribute; private System.Windows.Forms.DataGridViewTextBoxColumn Column1; private System.Windows.Forms.DataGridViewTextBoxColumn Column2; private System.Windows.Forms.ListBox listBox_Mes; private System.Windows.Forms.PictureBox pictureBox1; private System.Windows.Forms.Button btn_SendImg; private System.Windows.Forms.OpenFileDialog openFileDialog1; private System.Windows.Forms.Label lab_ImgName; private System.Windows.Forms.Button btn_Stop; private System.Windows.Forms.Label label7; private System.Windows.Forms.Label label6; private System.Windows.Forms.Label label5; } }
运行代码:
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.Sockets; using System.Net; using System.Threading; using System.Drawing.Imaging; using System.IO; using System.Collections; using System.Xml; namespace SocketService { public partial class Form1 : Form { public Form1() { InitializeComponent(); } #region 参数声明 /// <summary> /// 字典 IP加客户端状态 /// </summary> static Dictionary<string, ClientState> dic_ip = new Dictionary<string, ClientState>(); /// <summary> /// 服务端启动的Socket /// </summary> Socket s_socket; #endregion /// <summary> /// 开启监听 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_StartSocket_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(this.txt_ip.Text.Trim()) && string.IsNullOrWhiteSpace(this.txt_port.Text.Trim()) && !string.IsNullOrWhiteSpace(this.txt_Monitor.Text.Trim())) { MessageBox.Show("输入不符合或已在监听"); return; } //获取IP PORT异步连接Socket string ip = this.txt_ip.Text.Trim(); int port = int.Parse(this.txt_port.Text.Trim()); s_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { s_socket.Bind(new IPEndPoint(IPAddress.Parse(ip), port)); s_socket.Listen();//同时连接的最大连接数 s_socket.BeginAccept(new AsyncCallback(Accept), s_socket);//获取连接 this.txt_Monitor.Text = ip + ":" + port; this.txt_ip.Enabled = false; this.txt_port.Enabled = false; } catch (Exception ex) { Console.WriteLine("error ex=" + ex.Message + " " + ex.StackTrace); } } /// <summary> /// 异步连接回调 获取请求Socket 添加信息到控件 /// </summary> /// <param name="ar"></param> private void Accept(IAsyncResult ar) { try { //获取连接Socket 创建新的连接 Socket myServer = ar.AsyncState as Socket; Socket service = myServer.EndAccept(ar); #region 内部逻辑 UI处理部分 ClientState obj = new ClientState(); obj.clientSocket = service; //添加到字典 dic_ip.Add(service.RemoteEndPoint.ToString(), obj); var point = service.RemoteEndPoint.ToString().Split(':'); this.BeginInvoke((MethodInvoker)delegate () { //获取IP 端口添加到控件 int index = this.dataGridView1.Rows.Add(); dataGridView1.Rows[index].Cells[].Value = point[]; dataGridView1.Rows[index].Cells[].Value = point[]; }); #endregion //接收连接Socket数据 service.BeginReceive(obj.buffer, , ClientState.bufsize, SocketFlags.None, new AsyncCallback(ReadCallback), obj); myServer.BeginAccept(new AsyncCallback(Accept), myServer);//等待下一个连接 } catch (Exception ex) { Console.WriteLine("服务端关闭"+ex.Message+" "+ex.StackTrace); } } /// <summary> /// 发送消息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_SendMes_Click(object sender, EventArgs e) { try { ].Value + ].Value; SendSocket send = new SendSocket() { Message = this.txt_Mes.Text.Trim() }; Send(dic_ip[key].clientSocket, send.ToArray()); } catch (Exception ex) { MessageBox.Show("error ex=" + ex.Message + " " + ex.StackTrace); } } /// <summary> /// 发送震动 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_SendShake_Click(object sender, EventArgs e) { //根据选中的IP端口 获取对应客户端Socket ].Value + ].Value; if (dic_ip.ContainsKey(key)) { SendSocket send = new SendSocket() { SendShake = true, Message = "震动", }; Send(dic_ip[key].clientSocket, send.ToArray()); } else { MessageBox.Show("选中数据无效,找不到客户端"); } } /// <summary> /// 发送图片 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_SendImg_Click(object sender, EventArgs e) { ].Value + ].Value; if (dic_ip.ContainsKey(key)) { //初始化一个OpenFileDialog类 OpenFileDialog fileDialog = new OpenFileDialog(); //判断用户是否正确的选择了文件 if (fileDialog.ShowDialog() == DialogResult.OK) { string extension = Path.GetExtension(fileDialog.FileName); string[] str = new string[] { ".gif", ".jpge", ".jpg", "bmp" };//准许上传格式 if (!((IList)str).Contains(extension)) { MessageBox.Show("仅能上传gif,jpge,jpg,bmp格式的图片!"); } FileInfo fileInfo = new FileInfo(fileDialog.FileName); )//不能大于25 { MessageBox.Show("图片不能大于25M"); } //将图片转成base64发送 SendSocket send = new SendSocket() { SendImg = true, ImgName = fileDialog.SafeFileName, }; using (FileStream file = new FileStream(fileDialog.FileName, FileMode.Open, FileAccess.Read)) { var imgby = new byte[file.Length]; file.Read(imgby, , imgby.Length); send.ImgBase64 = Convert.ToBase64String(imgby); } Send(dic_ip[key].clientSocket, send.ToArray()); } } else { MessageBox.Show("请正确选择,选中客户端不存在"); } } #region Socket 发送和接收 /// <summary> /// 发送消息 /// </summary> /// <param name="s_socket">指定客户端socket</param> /// <param name="message">发送消息</param> /// <param name="Shake">发送消息</param> private void Send(Socket c_socket, byte[] by) { try { //发送 c_socket.BeginSend(by, , by.Length, SocketFlags.None, asyncResult => { try { //完成消息发送 int len = c_socket.EndSend(asyncResult); } catch (Exception ex) { if (c_socket != null) { c_socket.Close(); c_socket = null; } Console.WriteLine("error ex=" + ex.Message + " " + ex.StackTrace); } }, null); this.txt_Mes.Text = null; } catch (Exception ex) { if (c_socket != null) { c_socket.Close(); c_socket = null; } Console.WriteLine("error ex=" + ex.Message + " " + ex.StackTrace); } } /// <summary> /// 数据接收 /// </summary> /// <param name="ar">请求的Socket</param> private void ReadCallback(IAsyncResult ar) { //获取并保存 ClientState obj = ar.AsyncState as ClientState; Socket c_socket = obj.clientSocket; try { int bytes = c_socket.EndReceive(ar); #region 接收数据 ) { byte[] buf = obj.buffer; //判断头部是否正确 标识0-3 8888 ] == && buf[] == && buf[] == && buf[] == ) { //判断是否为震动 标识12-15 1111 ] == && buf[] == && buf[] == && buf[] == ) { //实现震动效果 this.BeginInvoke((MethodInvoker)delegate () { , y = ; ; i < ; i++) { this.Left += x; Thread.Sleep(y); this.Top += x; Thread.Sleep(y); this.Left -= x; Thread.Sleep(y); this.Top -= x; Thread.Sleep(y); } }); } else { );//获取数据总长度 //获取内容长度 ); obj.buffer = new byte[contentLength]; ; while (readDataPtr < contentLength)//判断内容是否接收完成 { var re = c_socket.Receive(obj.buffer, readDataPtr, contentLength - readDataPtr, SocketFlags.None);//接收内容 readDataPtr += re; } //转换显示 UTF8 , contentLength); ] == && buf[] == && buf[] == && buf[] == ) { #region 解析报文 //显示到listbox this.BeginInvoke((MethodInvoker)delegate () { var time = DateTime.Now.ToString(); this.listBox_Mes.Items.Add(time + " " + c_socket.RemoteEndPoint.ToString()); this.listBox_Mes.Items.Add("接收到图片"); this.listBox_attribute.Items.Add(DateTime.Now.ToString()); this.listBox_attribute.Items.Add("数据总长度 " + totalLength + " 内容长度 " + contentLength); }); try { //解析XML 获取图片名称和BASE64字符串 XmlDocument document = new XmlDocument(); document.LoadXml(str); XmlNodeList root = document.SelectNodes("/ImgMessage"); string imgNmae = string.Empty, imgBase64 = string.Empty; foreach (XmlElement node in root) { imgNmae = node.GetElementsByTagName(].InnerText; imgBase64 = node.GetElementsByTagName(].InnerText; } //BASE64转成图片 byte[] imgbuf = Convert.FromBase64String(imgBase64); using (System.IO.MemoryStream m_Str = new System.IO.MemoryStream(imgbuf)) { using (Bitmap bit = new Bitmap(m_Str)) { //保存到本地并上屏 var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, imgNmae); bit.Save(path); pictureBox1.BeginInvoke((MethodInvoker)delegate () { lab_ImgName.Text = imgNmae; pictureBox1.ImageLocation = path; }); } } } catch (Exception ex) { Console.WriteLine(ex.Message + " " + ex.StackTrace); } #endregion } else { //显示到listbox this.BeginInvoke((MethodInvoker)delegate () { var time = DateTime.Now.ToString(); this.listBox_Mes.Items.Add(time + " " + c_socket.RemoteEndPoint.ToString()); this.listBox_Mes.Items.Add(str); this.listBox_attribute.Items.Add(DateTime.Now.ToString()); this.listBox_attribute.Items.Add("数据总长度 " + totalLength + " 内容长度 " + contentLength); }); } } } //接收完成 重新给出buffer接收 obj.buffer = new byte[ClientState.bufsize]; c_socket.BeginReceive(obj.buffer, , ClientState.bufsize, , new AsyncCallback(ReadCallback), obj); } else { UpdateControls(c_socket); } #endregion } catch (Exception ex) { UpdateControls(c_socket); } } /// <summary> /// 关闭指定客户端 更新控件 /// </summary> /// <param name="socket"></param> public void UpdateControls(Socket socket) { dic_ip.Remove(socket.RemoteEndPoint.ToString()); List<int> list = new List<int>(); ; i < dataGridView1.RowCount; i++) { ].Value + ].Value; if (val != null && val.ToString() == socket.RemoteEndPoint.ToString()) { list.Add(i); } } this.BeginInvoke((MethodInvoker)delegate () { foreach (var item in list) { dataGridView1.Rows.Remove(dataGridView1.Rows[item]); } }); socket.Close(); socket.Dispose(); } #endregion /// <summary> /// 停止 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_Stop_Click(object sender, EventArgs e) { s_socket.Close(); this.txt_ip.Enabled = true; this.txt_port.Enabled = true; this.txt_Monitor.Text = null; } } }
声明的类:
using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; namespace SocketService { /// <summary> /// 接收消息 /// </summary> public class ClientState { public Socket clientSocket = null; ; public byte[] buffer = new byte[bufsize]; public StringBuilder str = new StringBuilder(); } /// <summary> /// 显示客户端IP 端口 /// </summary> public class ClientClass { public string IP { get; set; } public string Port { get; set; } } /// <summary> /// 0-3 标识码 4-7 总长度 8-11 内容长度 12-15补0 16开始为内容 /// </summary> public class SendSocket { /// <summary> /// 头 标识8888 /// </summary> ] { 0x08, 0x08, 0x08, 0x08 }; /// <summary> /// 文本消息 /// </summary> public string Message; /// <summary> /// 是否发送震动 /// </summary> public bool SendShake = false; /// <summary> /// 是否发送图片 /// </summary> public bool SendImg = false; /// <summary> /// 图片名称 /// </summary> public string ImgName; /// <summary> /// 图片数据 /// </summary> public string ImgBase64; /// <summary> /// 组成特定格式的byte数据 /// 12-15 为指定发送内容 1111(震动) 2222(图片数据) /// </summary> /// <param name="mes">文本消息</param> /// <param name="Shake">震动</param> /// <param name="Img">图片</param> /// <returns>特定格式的byte</returns> public byte[] ToArray() { if (SendImg)//是否发送图片 { //组成XML接收 可以接收相关图片数据 StringBuilder xmlResult = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); xmlResult.Append("<ImgMessage>"); xmlResult.AppendFormat("<ImgName>{0}</ImgName>", ImgName); xmlResult.AppendFormat("<ImgBase64>{0}</ImgBase64>", ImgBase64); xmlResult.Append("</ImgMessage>"); Message = xmlResult.ToString(); } byte[] byteData = Encoding.UTF8.GetBytes(Message);//内容 + byteData.Length;//总长度 byte[] SendBy = new byte[count]; Array.Copy(Header, , SendBy, , Header.Length);//添加头 byte[] CountBy = BitConverter.GetBytes(count); Array.Copy(CountBy, , SendBy, , CountBy.Length);//总长度 byte[] ContentBy = BitConverter.GetBytes(byteData.Length); Array.Copy(ContentBy, , SendBy, , ContentBy.Length);//内容长度 if (SendShake)//发动震动 { ] { , , , }; Array.Copy(shakeBy, , SendBy, , shakeBy.Length);//震动 } if (SendImg)//发送图片 { ] { , , , }; Array.Copy(imgBy, , SendBy, , imgBy.Length);//图片 } Array.Copy(byteData, , SendBy, , byteData.Length);//内容 return SendBy; } } }
客户端
窗体(UI)代码:
namespace SocketClient { partial class Form1 { /// <summary> /// 必需的设计器变量。 /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 清理所有正在使用的资源。 /// </summary> /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows 窗体设计器生成的代码 /// <summary> /// 设计器支持所需的方法 - 不要修改 /// 使用代码编辑器修改此方法的内容。 /// </summary> private void InitializeComponent() { this.btn_StopSocket = new System.Windows.Forms.Button(); this.txt_Monitor = new System.Windows.Forms.TextBox(); this.label3 = new System.Windows.Forms.Label(); this.btn_StartSocket = new System.Windows.Forms.Button(); this.txt_port = new System.Windows.Forms.TextBox(); this.label2 = new System.Windows.Forms.Label(); this.txt_ip = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.btn_SendImg = new System.Windows.Forms.Button(); this.btn_SendShake = new System.Windows.Forms.Button(); this.btn_SendMes = new System.Windows.Forms.Button(); this.label4 = new System.Windows.Forms.Label(); this.txt_mes = new System.Windows.Forms.TextBox(); this.listBox1 = new System.Windows.Forms.ListBox(); this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); this.lab_ImgName = new System.Windows.Forms.Label(); this.groupBox1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); this.SuspendLayout(); // // btn_StopSocket // , ); this.btn_StopSocket.Name = "btn_StopSocket"; , ); ; this.btn_StopSocket.Text = "取消连接"; this.btn_StopSocket.UseVisualStyleBackColor = true; this.btn_StopSocket.Click += new System.EventHandler(this.btn_StopSocket_Click); // // txt_Monitor // , ); this.txt_Monitor.Name = "txt_Monitor"; this.txt_Monitor.ReadOnly = true; , ); ; // // label3 // this.label3.AutoSize = true; , ); this.label3.Name = "label3"; , ); ; this.label3.Text = "正在连接"; // // btn_StartSocket // , ); this.btn_StartSocket.Name = "btn_StartSocket"; , ); ; this.btn_StartSocket.Text = "开始连接"; this.btn_StartSocket.UseVisualStyleBackColor = true; this.btn_StartSocket.Click += new System.EventHandler(this.btn_StartSocket_Click); // // txt_port // , ); this.txt_port.Name = "txt_port"; , ); ; "; // // label2 // this.label2.AutoSize = true; , ); this.label2.Name = "label2"; , ); ; this.label2.Text = "端口"; // // txt_ip // , ); this.txt_ip.Name = "txt_ip"; , ); ; this.txt_ip.Text = "127.0.0.1"; // // label1 // this.label1.AutoSize = true; , ); this.label1.Name = "label1"; , ); ; this.label1.Text = "IP"; // // groupBox1 // this.groupBox1.Controls.Add(this.lab_ImgName); this.groupBox1.Controls.Add(this.pictureBox1); this.groupBox1.Controls.Add(this.btn_SendImg); this.groupBox1.Controls.Add(this.btn_SendShake); this.groupBox1.Controls.Add(this.btn_SendMes); this.groupBox1.Controls.Add(this.label4); this.groupBox1.Controls.Add(this.txt_mes); this.groupBox1.Controls.Add(this.listBox1); , ); this.groupBox1.Name = "groupBox1"; , ); ; this.groupBox1.TabStop = false; this.groupBox1.Text = "发送与接收"; // // pictureBox1 // , ); this.pictureBox1.Name = "pictureBox1"; , ); this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; ; this.pictureBox1.TabStop = false; // // btn_SendImg // , ); this.btn_SendImg.Name = "btn_SendImg"; , ); ; this.btn_SendImg.Text = "发送图片"; this.btn_SendImg.UseVisualStyleBackColor = true; this.btn_SendImg.Click += new System.EventHandler(this.btn_SendImg_Click); // // btn_SendShake // , ); this.btn_SendShake.Name = "btn_SendShake"; , ); ; this.btn_SendShake.Text = "发送震动"; this.btn_SendShake.UseVisualStyleBackColor = true; this.btn_SendShake.Click += new System.EventHandler(this.btn_SendShake_Click); // // btn_SendMes // , ); this.btn_SendMes.Name = "btn_SendMes"; , ); ; this.btn_SendMes.Text = "消息发送"; this.btn_SendMes.UseVisualStyleBackColor = true; this.btn_SendMes.Click += new System.EventHandler(this.btn_SendMes_Click); // // label4 // this.label4.AutoSize = true; , ); this.label4.Name = "label4"; , ); ; this.label4.Text = "消息输入"; // // txt_mes // , ); this.txt_mes.Multiline = true; this.txt_mes.Name = "txt_mes"; , ); ; // // listBox1 // this.listBox1.FormattingEnabled = true; ; , ); this.listBox1.Name = "listBox1"; , ); ; // // openFileDialog1 // this.openFileDialog1.FileName = "openFileDialog1"; // // lab_ImgName // this.lab_ImgName.AutoSize = true; , ); this.lab_ImgName.Name = "lab_ImgName"; , ); ; // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; , ); this.Controls.Add(this.groupBox1); this.Controls.Add(this.btn_StopSocket); this.Controls.Add(this.txt_Monitor); this.Controls.Add(this.label3); this.Controls.Add(this.btn_StartSocket); this.Controls.Add(this.txt_port); this.Controls.Add(this.label2); this.Controls.Add(this.txt_ip); this.Controls.Add(this.label1); this.Name = "Form1"; this.Text = "客户端"; this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Button btn_StopSocket; private System.Windows.Forms.TextBox txt_Monitor; private System.Windows.Forms.Label label3; private System.Windows.Forms.Button btn_StartSocket; private System.Windows.Forms.TextBox txt_port; private System.Windows.Forms.Label label2; private System.Windows.Forms.TextBox txt_ip; private System.Windows.Forms.Label label1; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.Button btn_SendShake; private System.Windows.Forms.Button btn_SendMes; private System.Windows.Forms.Label label4; private System.Windows.Forms.TextBox txt_mes; private System.Windows.Forms.ListBox listBox1; private System.Windows.Forms.Button btn_SendImg; private System.Windows.Forms.OpenFileDialog openFileDialog1; private System.Windows.Forms.PictureBox pictureBox1; private System.Windows.Forms.Label lab_ImgName; } }
运行代码:
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.Sockets; using System.Net; using System.Threading; using System.IO; using System.Collections; using System.Drawing.Imaging; using System.Xml; namespace SocketClient { public partial class Form1 : Form { public Form1() { InitializeComponent(); } #region 参数声明 /// <summary> /// 根据IP:Port 存储值 /// </summary> static Dictionary<string, ServiceState> dic_ip = new Dictionary<string, ServiceState>(); /// <summary> /// 客户端socket /// </summary> Socket c_socket; Thread th_socket; ; #endregion /// <summary> /// 开启Scoket连接 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_StartSocket_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(this.txt_ip.Text.Trim()) && string.IsNullOrWhiteSpace(this.txt_port.Text.Trim()) && !string.IsNullOrWhiteSpace(this.txt_Monitor.Text.Trim())) { MessageBox.Show("输入不符合或已经连接"); return; } try { this.txt_ip.Enabled = false; this.txt_port.Enabled = false; Start(); th_socket = new Thread(MonitorSocker); th_socket.IsBackground = true; th_socket.Start(); } catch (Exception ex) { MessageBox.Show(ex.Message + " " + ex.StackTrace); this.txt_ip.Enabled = true; this.txt_port.Enabled = true; } } //监听Socket void MonitorSocker() { while (true) { && ConnectionResult != -)//通过错误码判断 { Start(); this.BeginInvoke((MethodInvoker)delegate () { this.label3.Text = "重连中.."; this.txt_Monitor.Text = "errorCode" + ConnectionResult.ToString(); }); dic_ip = new Dictionary<string, ServiceState>(); } Thread.Sleep(); } } /// <summary> /// 关闭Socket连接 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_StopSocket_Click(object sender, EventArgs e) { Stop(); } /// <summary> /// 发送文本消息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_SendMes_Click(object sender, EventArgs e) { try { SendSocket send = new SocketClient.SendSocket() { Message = this.txt_mes.Text.Trim(), }; Send(dic_ip[this.txt_Monitor.Text.Trim()].serviceSocket, send.ToArray()); this.txt_mes.Text = ""; } catch (Exception ex) { MessageBox.Show(ex.Message + " " + ex.StackTrace); } } /// <summary> /// 发送震动 /// </summary> private void btn_SendShake_Click(object sender, EventArgs e) { SendSocket send = new SocketClient.SendSocket() { SendShake = true, Message = "震动", }; Send(dic_ip[this.txt_Monitor.Text.Trim()].serviceSocket, send.ToArray()); } /// <summary> /// 发送图片数据 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_SendImg_Click(object sender, EventArgs e) { //初始化一个OpenFileDialog类 OpenFileDialog fileDialog = new OpenFileDialog(); //判断用户是否正确的选择了文件 if (fileDialog.ShowDialog() == DialogResult.OK) { string extension = Path.GetExtension(fileDialog.FileName); string[] str = new string[] { ".gif", ".jpge", ".jpg", "bmp" };//准许上传格式 if (!((IList)str).Contains(extension)) { MessageBox.Show("仅能上传gif,jpge,jpg,bmp格式的图片!"); } FileInfo fileInfo = new FileInfo(fileDialog.FileName); )//不能大于25 { MessageBox.Show("图片不能大于25M"); } //将图片转成base64发送 SendSocket send = new SendSocket() { SendImg = true, ImgName = fileDialog.SafeFileName, }; using (FileStream file = new FileStream(fileDialog.FileName, FileMode.Open, FileAccess.Read)) { var imgby = new byte[file.Length]; file.Read(imgby, , imgby.Length); send.ImgBase64 = Convert.ToBase64String(imgby); } Send(dic_ip[this.txt_Monitor.Text.Trim()].serviceSocket, send.ToArray()); } } /// <summary> /// 关闭socket /// </summary> public void Stop() { var key = this.txt_Monitor.Text.Trim(); if (dic_ip.ContainsKey(key)) { dic_ip.Remove(key); } if (c_socket == null) return; if (!c_socket.Connected) return; try { c_socket.Close(); } catch { } this.txt_ip.Enabled = true; this.txt_port.Enabled = true; this.txt_Monitor.Text = null; } /// <summary> /// 连接Socket /// </summary> public void Start() { try { string ip = this.txt_ip.Text.Trim(); int port = int.Parse(this.txt_port.Text.Trim()); var endPoint = new IPEndPoint(IPAddress.Parse(ip), port); c_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); c_socket.BeginConnect(endPoint, new AsyncCallback(Connect), c_socket); } catch (SocketException ex) { Console.WriteLine("error ex=" + ex.Message + " " + ex.StackTrace); this.txt_ip.Enabled = true; this.txt_port.Enabled = true; } } #region Socket 连接 发送 接收 /// <summary> /// 连接服务端 /// </summary> /// <param name="ar"></param> private void Connect(IAsyncResult ar) { try { ServiceState obj = new ServiceState(); Socket client = ar.AsyncState as Socket; obj.serviceSocket = client; //获取服务端信息 client.EndConnect(ar); //添加到字典集合 dic_ip.Add(client.RemoteEndPoint.ToString(), obj); //显示到txt文本 this.BeginInvoke((MethodInvoker)delegate () { this.txt_Monitor.Text = client.RemoteEndPoint.ToString(); }); //接收连接Socket数据 client.BeginReceive(obj.buffer, , ServiceState.bufsize, SocketFlags.None, new AsyncCallback(ReadCallback), obj); ConnectionResult = ; } catch (SocketException ex) { ConnectionResult = ex.ErrorCode; Console.WriteLine(ex.Message + " " + ex.StackTrace); } } /// <summary> /// 数据接收 /// </summary> /// <param name="ar"></param> private void ReadCallback(IAsyncResult ar) { ServiceState obj = ar.AsyncState as ServiceState; Socket s_socket = obj.serviceSocket; try { if (s_socket.Connected) { #region 接收数据处理 int bytes = s_socket.EndReceive(ar); ) { byte[] buf = obj.buffer; //判断头部是否正确 ] == && buf[] == && buf[] == && buf[] == ) { //判断是否为震动 标识12-15 1111 ] == && buf[] == && buf[] == && buf[] == ) { //实现震动效果 this.BeginInvoke((MethodInvoker)delegate () { , y = ; ; i < ; i++) { this.Left += x; Thread.Sleep(y); this.Top += x; Thread.Sleep(y); this.Left -= x; Thread.Sleep(y); this.Top -= x; Thread.Sleep(y); } }); } else { ); //获取内容长度 ); obj.buffer = new byte[contentLength]; ; while (readDataPtr < contentLength) { var re = c_socket.Receive(obj.buffer, readDataPtr, contentLength - readDataPtr, SocketFlags.None);//接收内容 readDataPtr += re; } //转换显示 , contentLength); //转换显示 UTF8 ] == && buf[] == && buf[] == && buf[] == ) { #region 解析报文 //解析XML 获取图片名称和BASE64字符串 XmlDocument document = new XmlDocument(); document.LoadXml(str); XmlNodeList root = document.SelectNodes("/ImgMessage"); string imgNmae = string.Empty, imgBase64 = string.Empty; foreach (XmlElement node in root) { imgNmae = node.GetElementsByTagName(].InnerText; imgBase64 = node.GetElementsByTagName(].InnerText; } //BASE64转成图片 byte[] imgbuf = Convert.FromBase64String(imgBase64); using (System.IO.MemoryStream m_Str = new System.IO.MemoryStream(imgbuf)) { using (Bitmap bit = new Bitmap(m_Str)) { //保存到本地并上屏 var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, imgNmae); bit.Save(path); pictureBox1.BeginInvoke((MethodInvoker)delegate () { lab_ImgName.Text = imgNmae; pictureBox1.ImageLocation = path; }); } } #endregion } else { this.BeginInvoke((MethodInvoker)delegate () { this.listBox1.Items.Add(DateTime.Now.ToString() + ":" + " 数据总长度 " + totalLength + " 内容长度 " + contentLength); this.listBox1.Items.Add(s_socket.RemoteEndPoint.ToString() + " " + str); }); } } } obj.buffer = new byte[ServiceState.bufsize]; s_socket.BeginReceive(obj.buffer, , ServiceState.bufsize, , new AsyncCallback(ReadCallback), obj); } #endregion } } catch (SocketException ex) { ConnectionResult = ex.ErrorCode; Console.WriteLine(ex.Message + " " + ex.StackTrace); } } /// <summary> /// 发送 /// </summary> /// <param name="s_socket"></param> /// <param name="mes"></param> private void Send(Socket s_socket, byte[] by) { try { //发送 s_socket.BeginSend(by, , by.Length, SocketFlags.None, asyncResult => { try { //完成消息发送 int len = s_socket.EndSend(asyncResult); } catch (SocketException ex) { ConnectionResult = ex.ErrorCode; Console.WriteLine(ex.Message + " " + ex.StackTrace); } }, null); } catch (Exception ex) { Console.WriteLine(ex.Message + " " + ex.StackTrace); } } #endregion } }
声明的类:
using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using System.Xml; namespace SocketClient { /// <summary> /// 接收消息 /// </summary> public class ServiceState { public Socket serviceSocket = null; ; public byte[] buffer = new byte[bufsize]; public StringBuilder str = new StringBuilder(); } /// <summary> /// 0-3 标识码 4-7 总长度 8-11 内容长度 12-15 补0/震动补1 16开始为内容 /// </summary> public class SendSocket { /// <summary> /// 头 标识8888 /// </summary> ] { 0x08, 0x08, 0x08, 0x08 }; /// <summary> /// 文本消息 /// </summary> public string Message; /// <summary> /// 是否发送震动 /// </summary> public bool SendShake = false; /// <summary> /// 是否发送图片 /// </summary> public bool SendImg = false; /// <summary> /// 图片名称 /// </summary> public string ImgName; /// <summary> /// 图片数据 /// </summary> public string ImgBase64; /// <summary> /// 组成特定格式的byte数据 /// 12-15 为指定发送内容 1111(震动) 2222(图片数据) /// </summary> /// <param name="mes">文本消息</param> /// <param name="Shake">震动</param> /// <param name="Img">图片</param> /// <returns>特定格式的byte</returns> public byte[] ToArray() { if (SendImg)//是否发送图片 { //组成XML接收 可以接收相关图片数据 StringBuilder xmlResult = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); xmlResult.Append("<ImgMessage>"); xmlResult.AppendFormat("<ImgName>{0}</ImgName>", ImgName); xmlResult.AppendFormat("<ImgBase64>{0}</ImgBase64>", ImgBase64); xmlResult.Append("</ImgMessage>"); Message = xmlResult.ToString(); } byte[] byteData = Encoding.UTF8.GetBytes(Message);//内容 + byteData.Length;//总长度 byte[] SendBy = new byte[count]; Array.Copy(Header, , SendBy, , Header.Length);//添加头 byte[] CountBy = BitConverter.GetBytes(count); Array.Copy(CountBy, , SendBy, , CountBy.Length);//总长度 byte[] ContentBy = BitConverter.GetBytes(byteData.Length); Array.Copy(ContentBy, , SendBy, , ContentBy.Length);//内容长度 if (SendShake)//发动震动 { ] { , , , }; Array.Copy(shakeBy, , SendBy, , shakeBy.Length);//震动 } if (SendImg)//发送图片 { ] { , , , }; Array.Copy(imgBy, , SendBy, , imgBy.Length);//图片 } Array.Copy(byteData, , SendBy, , byteData.Length);//内容 return SendBy; } } }
百度云盘下载地址:
链接:https://pan.baidu.com/s/1l8N1IQJn7Os15PIuSs6YjA
提取码:dprj
C# Socket异步实现消息发送--附带源码的更多相关文章
- Log4Net 日志配置[附带源码]
前述 园子里有许多人对log4net这款开源的日志记录控件有很多介绍.在这里个人再做一次总结,希望对以后有所帮助,需要的时候可以直接使用,减少查阅资料的时间.利用log4net可以方便地将日志信息记录 ...
- SpringMVC关于json、xml自动转换的原理研究[附带源码分析 --转
SpringMVC关于json.xml自动转换的原理研究[附带源码分析] 原文地址:http://www.cnblogs.com/fangjian0423/p/springMVC-xml-json-c ...
- 【Hook技术】实现从"任务管理器"中保护进程不被关闭 + 附带源码 + 进程保护知识扩展
[Hook技术]实现从"任务管理器"中保护进程不被关闭 + 附带源码 + 进程保护知识扩展 公司有个监控程序涉及到进程的保护问题,需要避免用户通过任务管理器结束掉监控进程,这里使用 ...
- 【轮子狂魔】抛弃IIS,打造个性的Web Server - WebAPI/Lua/MVC(附带源码)
引言 此篇是<[轮子狂魔]抛弃IIS,向天借个HttpListener - 基础篇(附带源码)>的续篇,也可以说是提高篇,如果你对HttpListener不甚了解的话,建议先看下基础篇. ...
- iOS 指南针的制作 附带源码
iOS 指南针的制作 附带源码 代码下载地址: http://vdisk.weibo.com/s/HK4yE http://pan.baidu.com/share/link?shareid=7 ...
- Python机器学习经典实例电子版和附带源码
Python机器学习经典实例电子版和附带源码 下载:https://pan.baidu.com/s/1m6ODNJk--PWHW8Vdsdjs-g 提取码:nyc0 分享更多python数据分析相关电 ...
- C#的Socket简单实现消息发送
Socket一般用于网络之间的通信,在这里,实现的是服务端与客户端的简单消息通信.首先是客户端的搭建,一般步骤是先建立Socket绑定本地的IP和端口,并对远端连接进行连接进行监听,这里的监听一般开启 ...
- iOS Socket 整理以及CocoaAsyncSocket、SRWebSocket源码解析(一)
写在准备动手的时候: Socket通讯在iOS中也是很常见,自己最近也一直在学习Telegram这个开源项目,Telegram就是在Socket的基础上做的即时通讯,这个相信了解这个开源项目的也都知道 ...
- Android进阶:三、这一次,我们用最详细的方式解析Android消息机制的源码
决定再写一次有关Handler的源码 Handler源码解析 一.创建Handler对象 使用handler最简单的方式:直接new一个Handler的对象 Handler handler = new ...
随机推荐
- Java基础-SSM之Spring的POJO(Plain Old Java Object)实现AOP
Java基础-SSM之Spring的POJO(Plain Old Java Object)实现AOP 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 上次我分享过Spring传统的A ...
- Hive SQL 编译过程
转自:http://www.open-open.com/lib/view/open1400644430159.html Hive跟Impala貌似都是公司或者研究所常用的系统,前者更稳定点,实现方式是 ...
- spring注解 @Scheduled(cron = "0 0 1 * * *")实现定时的执行任务
@Scheduled(cron = "0 0 1 * * *") 在使用该注解以前请做好以下准备工作,配置好相应的xm文件. 配置定时注解的步骤:http://blog.csdn. ...
- 流媒体技术学习笔记之(十)HLS协议直播延时优化(35s到10S)
1.首先要了解HLS延时的机制,也就是为什么会延时,延时主要发生在什么地方. HTTP Live Streaming 并不是一个真正实时的流媒体系统,这是因为对应于媒体分段的大小和持续时间有一定潜在的 ...
- angularJs入门篇-hello world 开头
AngularJS 采用了完全不同的解决方案,它创建实时视图模板代替视图,而不是将数据合并进模板之后更新DOM. 任何一个独立视图组件中的值都是 动态替换的.这个功能可以说是AngularJS中最重要 ...
- artDialog学习之旅(二)之扩展方法详解
名称 描述 核心方法 art.dialog.top 获取artDialog可用最高层window对象.这与直接使用window.top不同,它能排除artDialog对象不存在已经或者顶层页面为框架集 ...
- str和unicode类
在py2中,分为两类,str和unicode 而在py3中,分为两类,byte和str py2中的str等同于py3中的byte 首先明确一点,我们编辑好一段文本,python并不知道我们的文本是以什 ...
- blog迁移
blog迁移到: https://github.com/for-firecat/
- MVC常用特性使用
简介 在以前的文章中,我和大家讨论如何用SingalR和数据库通知来完成一个消息监控应用. 在上一篇文章中,我介绍了如何在MVC中对MongoDB进行CRUD操作. 今天,我将继续介绍一些在开发中非常 ...
- flask基础之请求钩子(十二)
前言 什么是请求钩子?在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要统一处理,为了让每个视图函数避免编写重复功能的代码,flask提供了统一的接口可以添加这些处理函数,即请求钩子. 请求钩子 ...