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 ...
随机推荐
- map经典代码---java基础
package com.mon11.day6; import java.util.HashMap; import java.util.Map; /** * 类说明 :实现英文简称和中文全名之间的键值对 ...
- get请求中的url encode问题
首先发表一下感慨,Python的requests模块确实太简便,省却了很多的转码等等等等的问题,但这也是缺点,对于我这种基础不好的同学来说让我少知道了许多本来应该知道的东西. url encode: ...
- java CountDownLatch的使用
CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行.使用一个计数器进行实现.计数器初始值为线程的数量.当每一个线程完成自己任务后,计数器的值就会减一.当计数器的值 ...
- HDU 1229 还是A+B(A+B陶冶情操)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1229 解题报告:A+B #include<cstdio> int main() { int ...
- c++刷题(33/100)笔试题1
笔试总共2小时,三道题,时间挺充裕的,但是最后只做了一道,原因在于自己很浮躁,不审题,不仔细思考.没过的两道都是稍微改一下代码就能过,但是没过就是没过,要引以为戒 题目1: 小W有一个电子时钟用于显示 ...
- 第7月第12天 opengles background
1. After your app exits its applicationDidEnterBackground: method, it must not make any new OpenGL E ...
- Python程序员之面试必回习题
写在前面 近日恰逢学生毕业季,课程后期大家“期待+苦逼”的时刻莫过于每天早上内容回顾和面试题问答部分[临近毕业每天课前用40-60分钟对之前内容回顾.提问和补充,专挑班里不爱说话就的同学回答]. 期待 ...
- 【算法】Huffman编码(数据结构+算法)
1.描述 Huffman编码,将字符串利用C++编码输出该字符串的Huffman编码. Huffman树是一种特殊结构的二叉树,由Huffman树设计的二进制前缀编码,也称为Huffman编码在通信领 ...
- start-stop-daemon 启动停止系统守护进程
1.start-stop-daemon start-stop-daemon是一个Debian体系里的一个守护进程管理软件,可以用指定的用户启停软件.CentOS有自己的daemon()机制(在/etc ...
- Linux常见问题总结【转】
作为一名合格的 Linux 运维工程师,一定要有一套清晰.明确的解决故障思路,当问题出现时,才能迅速定位.解决问题,这里给出一个处理问题的一般思路: 重视报错提示信息:每个错误的出现,都是给出错误提示 ...