当前位置:
首页 > Python基础教程 >
-
C#教程之C# Socket异步实现消息发送--附带源码(3)
try
{
var key = dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[0].Value + ":" + dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[1].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
var key = dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[0].Value + ":" + dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[1].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)
{
var key = dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[0].Value + ":" + dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[1].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);
if (fileInfo.Length > 26214400)//不能大于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, 0, 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, 0, 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 接收数据
if (bytes == 16)
{
byte[] buf = obj.buffer;
//判断头部是否正确 标识0-3 8888
if (buf[0] == 8 && buf[1] == 8 && buf[2] == 8 && buf[3] == 8)
{
//判断是否为震动 标识12-15 1111
if (buf[12] == 1 && buf[13] == 1 && buf[14] == 1 && buf[15] == 1)
{
//实现震动效果
this.BeginInvoke((MethodInvoker)delegate ()
{
int x = 5, y = 10;
for (int i = 0; i < 5; 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
{
int totalLength = BitConverter.ToInt32(buf, 4);//获取数据总长度
//获取内容长度
int contentLength = BitConverter.ToInt32(buf, 8);
obj.buffer = new byte[contentLength];
int readDataPtr = 0;
while (readDataPtr < contentLength)//判断内容是否接收完成
{
var re = c_socket.Receive(obj.buffer, readDataPtr, contentLength - readDataPtr, SocketFlags.None);//接收内容
readDataPtr += re;
}
//转换显示 UTF8
var str = Encoding.UTF8.GetString(obj.buffer, 0, contentLength);
if (buf[12] == 2 && buf[13] == 2 && buf[14] == 2 && buf[15] == 2)
{
#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("ImgName")[0].InnerText;
imgBase64 = node.GetElementsByTagName("ImgBase64")[0].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, 0, ClientState.bufsize, 0, 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>();
for (int i = 0; i < dataGridView1.RowCount; i++)
{
var val = dataGridView1.Rows[i].Cells[0].Value + ":" + dataGridView1.Rows[i].Cells[1].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 const int bufsize = 16; 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> byte[] Header = new byte[4] { 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);//内容 int count = 16 + byteData.Length;//总长度 byte[] SendBy = new byte[count]; Array.Copy(Header, 0, SendBy, 0, Header.Length);//添加头 byte[] CountBy = BitConverter.GetBytes(count); Array.Copy(CountBy, 0, SendBy, 4, CountBy.Length);//总长度 byte[] ContentBy = BitConverter.GetBytes(byteData.Length); Array.Copy(ContentBy, 0, SendBy, 8, ContentBy.Length);//内容长度 if (SendShake)//发动震动 { var shakeBy = new byte[4] { 1, 1, 1, 1 }; Array.Copy(shakeBy, 0, SendBy, 12, shakeBy.Length);//震动 } if (SendImg)//发送图片 { var imgBy = new byte[4] { 2, 2, 2, 2 }; Array.Copy(imgBy, 0, SendBy, 12, imgBy.Length);//图片 } Array.Copy(byteData, 0, SendBy, 16, 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
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式