目录
WebSocket
1.需求
在使用之前,引入Fleck插件,下面案例将采用winfrom作为服务器,html为客户端
需要注意的是,本案例经过测试有一个问题,就是客户端如果连接上服务器后,如果长时间不通讯,那么连接会自动断开,这里其实可以写一个类似TCP协议的心跳机制来解决这个问题。
2.WebSocket 封装
web_socket代码
using Fleck;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WebSocket
{
public class Web_Socket
{
//客户端url以及其对应的Socket对象字典
IDictionary<string, IWebSocketConnection> dic_Sockets = new Dictionary<string, IWebSocketConnection>();
//创建一个 websocket ,0.0.0.0 为监听所有的的地址
WebSocketServer server = new WebSocketServer("ws://0.0.0.0:30000");
//打开连接委托
public delegate void _OnOpen(string ip);
public event _OnOpen OnOpen;
//关闭连接委托
public delegate void _OnClose(string ip);
public event _OnClose OnClose;
//当收到消息
public delegate void _OnMessage(string ip, string msg);
public event _OnMessage OnMessage;
/// <summary>
/// 初始化
/// </summary>
private void Init()
{
//出错后进行重启
server.RestartAfterListenError = true;
//开始监听
server.Start(socket =>
{
//连接建立事件
socket.OnOpen = () =>
{
//获取客户端网页的url
string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
dic_Sockets.Add(clientUrl, socket);
if (OnOpen != null) OnOpen(clientUrl);
Console.WriteLine(DateTime.Now.ToString() + " | 服务器:和客户端网页:" + clientUrl + " 建立WebSock连接!");
};
//连接关闭事件
socket.OnClose = () =>
{
string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
//如果存在这个客户端,那么对这个socket进行移除
if (dic_Sockets.ContainsKey(clientUrl))
{
dic_Sockets.Remove(clientUrl);
if (OnClose != null) OnClose(clientUrl);
}
Console.WriteLine(DateTime.Now.ToString() + " | 服务器:和客户端网页:" + clientUrl + " 断开WebSock连接!");
};
//接受客户端网页消息事件
socket.OnMessage = message =>
{
string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
Receive(clientUrl, message);
if (OnMessage != null) OnMessage(clientUrl, message);
};
});
}
/// <summary>
/// 向客户端发送消息
/// </summary>
/// <param name="webSocketConnection">客户端实例</param>
/// <param name="message">消息内容</param>
public void Send(string clientUrl, string message)
{
IWebSocketConnection webSocketConnection = GetUserSocketInstance(clientUrl);
if (webSocketConnection != null)
{
if (webSocketConnection.IsAvailable)
{
webSocketConnection.Send(message);
}
}
}
/// <summary>
/// 接收消息
/// </summary>
/// <param name="clientUrl"></param>
/// <param name="message"></param>
private void Receive(string clientUrl, string message)
{
Console.WriteLine(DateTime.Now.ToString() + " | 服务器:【收到】来客户端网页:" + clientUrl + "的信息:\n" + message);
}
/// <summary>
/// 获取用户实例
/// </summary>
/// <param name="clientUrl">用户的地址</param>
public IWebSocketConnection GetUserSocketInstance(string clientUrl)
{
if (dic_Sockets.ContainsKey(clientUrl))
return dic_Sockets[clientUrl];
else
return null;
}
/// <summary>
/// 关闭某一个用户的连接
/// </summary>
/// <param name="clientUrl"></param>
public void CloseUserConnect(string clientUrl)
{
IWebSocketConnection webSocketConnection = GetUserSocketInstance(clientUrl);
if (webSocketConnection != null)
webSocketConnection.Close();
}
/// <summary>
/// 关闭与客户端的所有的连接
/// </summary>
public void CloseAllConnect()
{
foreach (var item in dic_Sockets.Values)
{
if (item != null)
{
item.Close();
}
}
}
public Web_Socket()
{
Init();
}
}
}
3.前端部分
winform 界面
Form1代码:
using Fleck;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WebSocket
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Web_Socket webSocket = new Web_Socket();
private void Form1_Load(object sender, EventArgs e)
{
webSocket.OnOpen += this.OnOpen;
webSocket.OnClose += this.OnClose;
webSocket.OnMessage += this.OnMessage;
Init();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
webSocket.CloseAllConnect();
}
private void Init()
{
}
//当有客户端连接
private void OnOpen(string clientUrl)
{
this.Invoke(new MethodInvoker(delegate
{
ComboBox_IPAddres.Items.Add(clientUrl);
if (ComboBox_IPAddres.Items.Count > 0)
ComboBox_IPAddres.SelectedIndex = 0;
ListBox_IPList.Items.Insert(ListBox_IPList.Items.Count, clientUrl);
}));
AddLogToListView("用户加入", string.Empty, string.Format("IP:{0} 加入了连接", clientUrl), true);
}
//当客户端关闭
private void OnClose(string clientUrl)
{
this.Invoke(new MethodInvoker(delegate
{
ComboBox_IPAddres.Items.Remove(clientUrl);
ListBox_IPList.Items.Remove(clientUrl);
}));
AddLogToListView("用户退出", string.Empty, string.Format("IP:{0} 关闭了连接", clientUrl), true);
}
//当收到客户端消息
private void OnMessage(string clientUrl, string message)
{
AddLogToListView("服务器接收", clientUrl, message);
}
/// <summary>
/// 添加日志到日志列表
/// </summary>
/// <param name="clientUrl"></param>
/// <param name="message"></param>
private void AddLogToListView(string title, string clientUrl, string message, bool rest = false)
{
this.Invoke(new MethodInvoker(delegate
{
int len = ListBox_MessageList.Items.Count;
if (!rest)
ListBox_MessageList.Items.Insert(len, string.Format("[{0}] IP:{1} 内容:{2}", title, clientUrl, message));
else
ListBox_MessageList.Items.Insert(len, string.Format("[{0}] {1}", title, message));
}));
}
/// <summary>
/// 发送按钮点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Send_Click(object sender, EventArgs e)
{
string clientUrl = ComboBox_IPAddres.Text;
string content = TextBox_Message.Text;
if (string.IsNullOrEmpty(content))
{
MessageBox.Show("发送内容为空");
return;
}
if (string.IsNullOrEmpty(clientUrl))
{
MessageBox.Show("请选择一个IP地址");
return;
}
webSocket.Send(clientUrl, content);
TextBox_Message.Text = string.Empty;
AddLogToListView("服务器发送", clientUrl, content);
}
}
}
4.网页端
html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>websocket client</title>
<script type="text/javascript">
var start = function () {
var inc = document.getElementById('incomming');
var wsImpl = window.WebSocket || window.MozWebSocket;
var form = document.getElementById('sendForm');
var input = document.getElementById('sendText');
inc.innerHTML += "连接服务器..<br/>";
// 创建一个新的websocket并连接
window.ws = new wsImpl('ws://localhost:30000/');
// 当数据来自服务器时,将调用此方法
ws.onmessage = function (evt) {
inc.innerHTML += ("[来自服务器的消息] " + evt.data + '<br/>');
console.log("[来自服务器的消息] " + evt.data);
};
// 当建立连接时,将调用此方法
ws.onopen = function () {
inc.innerHTML += '已建立连接.. <br/>';
};
// 当连接关闭时,将调用此方法
ws.onclose = function () {
inc.innerHTML += '连接已关闭.. <br/>';
}
form.addEventListener('submit', function (e) {
e.preventDefault();
var val = input.value;
ws.send(val);
input.value = "";
});
}
window.onload = start;
</script>
</head>
<body>
<form id="sendForm">
<span>输入内容按回车发送消息</span> <br/>
<input id="sendText" placeholder="Text to send" />
</form>
<pre id="incomming"></pre>
</body>
</html>
经过测试,发送,接收消息正常
HTTP通讯
代码:
using Newtonsoft.Json;
using System.IO;
using System.Net;
using System.Text;
namespace HTTP
{
public class RestClient
{
/// <summary>
/// Get请求
/// </summary>
/// <param name="url">请求url</param>
/// <returns></returns>
public static string Get(string url)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
if (req == null || req.GetResponse() == null)
return string.Empty;
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
if (resp == null)
return string.Empty;
using (Stream stream = resp.GetResponseStream())
{
//获取内容
using (StreamReader reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
/// <summary>
/// Post请求
/// </summary>
/// <param name="url"></param>
/// <param name="postData"></param>
/// <returns></returns>
public static string Post(string url, object postData)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
if (req == null)
return string.Empty;
req.Method = "POST";
req.ContentType = "application/json";
req.Timeout = 15000;
byte[] data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(postData));
//注意:无需手动指定长度 (否则可能会报流未处理完就关闭的异常,因为ContentLength时候会比真实post数据长度大)
//req.ContentLength = data.Length;
using (Stream reqStream = req.GetRequestStream())
{
reqStream.Write(data, 0, data.Length);
}
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
if (resp == null)
return string.Empty;
using (Stream stream = resp.GetResponseStream())
{
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
}
}
上面的Post请求在有些接口可能没有效果,可以使用下面的方法,其中第一个方法是无参数的Post请求,第二个方法只要将所需的Key和Value添加进字典就行了
/// <summary>
/// 指定Post地址使用Get 方式获取全部字符串
/// </summary>
/// <param name="url">请求后台地址</param>
/// <returns></returns>
public static string Post(string url)
{
string result = "";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Stream stream = resp.GetResponseStream();
//获取内容
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
result = reader.ReadToEnd();
}
return result;
}
/// <summary>
/// 指定Post地址使用Get 方式获取全部字符串
/// </summary>
/// <param name="url">请求后台地址</param>
/// <returns></returns>
public static string Post(string url, Dictionary<string, string> dic)
{
string result = "";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
#region 添加Post 参数
StringBuilder builder = new StringBuilder();
int i = 0;
foreach (var item in dic)
{
if (i > 0)
builder.Append("&");
builder.AppendFormat("{0}={1}", item.Key, item.Value);
i++;
}
byte[] data = Encoding.UTF8.GetBytes(builder.ToString());
req.ContentLength = data.Length;
using (Stream reqStream = req.GetRequestStream())
{
reqStream.Write(data, 0, data.Length);
reqStream.Close();
}
#endregion
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Stream stream = resp.GetResponseStream();
//获取响应内容
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
result = reader.ReadToEnd();
}
return result;
}
Task常用的两种使用方式
1.无返回值方式
代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MyTask
{
class Program
{
static void Main(string[] args)
{
List<Task> taskList = new List<Task>();
taskList.Add(Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
Console.WriteLine("1秒执行结束");
}));
taskList.Add(Task.Factory.StartNew(() =>
{
Thread.Sleep(800);
Console.WriteLine("o.8秒执行结束");
}));
Console.WriteLine("执行中");
TaskFactory taskFactory = new TaskFactory();
taskList.Add(taskFactory.ContinueWhenAll(taskList.ToArray(), tArray =>
{
Thread.Sleep(200);
Console.WriteLine("等待这些完成后执行");
}));
Console.ReadKey();
}
}
}
运行:
这里由于作了延时处理,执行顺序不一致
假设任务中出现异常:
代码:
taskList.Add(Task.Factory.StartNew(() =>
{
try
{
int a = int.Parse("");
}
catch (Exception ex)
{
Console.WriteLine("=========异常:" + ex.Message);
}
Console.WriteLine("=========第二种方式");
}));
运行:
2.有返回值方式
代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MyTask
{
class Program
{
static void Main(string[] args)
{
List<Task<int>> taskList1 = new List<Task<int>>();
taskList1.Add(Task<int>.Factory.StartNew(() =>
{
int num = 3 * 5;
Console.WriteLine("有返回值的任务队列 1");
return num;
}
));
taskList1.Add(Task<int>.Factory.StartNew(() =>
{
int num = 3 * 7;
Console.WriteLine("有返回值的任务队列 2");
return num;
}
));
new TaskFactory().ContinueWhenAll(taskList1.ToArray(), tArray =>
{
Console.WriteLine("有返回值的任务队列执行完毕");
foreach (Task<int> item in taskList1)
{
Console.WriteLine("执行结果:" + item.Result);
}
});
Console.ReadKey();
}
}
}
运行:
定时器
1.用线程
private void Form1_Load(object sender, EventArgs e){
timer = new System.Timers.Timer();
timer.Interval = 3000;
timer.AutoReset = false;
timer.Enabled = true;
timer.Elapsed += new System.Timers.ElapsedEventHandler(GetCurDateTime);
}
private void GetCurDateTime(object sender, System.Timers.ElapsedEventArgs e)
{
Label_Log.Text = string.Empty;
}
2.用winform 自带的组件
private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
private void Form1_Load(object sender, EventArgs e){
timer.Interval = 3000;
timer.Tick += GetCurDateTime;
timer.Enabled = true;
}
private void GetCurDateTime(object sender, EventArgs e)
{
Label_Log.Text = string.Empty;
}
比较两个对象的属性值是否相等
需要注意的是,两个对象中的字段必须是属性,带有get,set,否则无法识别,返回的就是false
代码
/// <summary>
/// 比较--两个类型一样的实体类对象的值
/// </summary>
/// <param name="oneT"></param>
/// <returns>返回true表示两个对象的数据相同,返回false表示不相同</returns>
private bool CompareType<T>(T oneT, T twoT)
{
bool result = true;//两个类型作比较时使用,如果有不一样的就false
Type typeOne = oneT.GetType();
Type typeTwo = twoT.GetType();
//如果两个T类型不一样 就不作比较
if (!typeOne.Equals(typeTwo)) { return false; }
PropertyInfo[] pisOne = typeOne.GetProperties(); //获取所有公共属性(Public)
PropertyInfo[] pisTwo = typeTwo.GetProperties();
//如果长度为0返回false
if (pisOne.Length <= 0 || pisTwo.Length <= 0)
{
return false;
}
//如果长度不一样,返回false
if (!(pisOne.Length.Equals(pisTwo.Length))) { return false; }
//遍历两个T类型,遍历属性,并作比较
for (int i = 0; i < pisOne.Length; i++)
{
//获取属性名
string oneName = pisOne[i].Name;
string twoName = pisTwo[i].Name;
//获取属性的值
object oneValue = pisOne[i].GetValue(oneT, null);
object twoValue = pisTwo[i].GetValue(twoT, null);
//比较,只比较值类型
if ((pisOne[i].PropertyType.IsValueType || pisOne[i].PropertyType.Name.StartsWith("String")) && (pisTwo[i].PropertyType.IsValueType || pisTwo[i].PropertyType.Name.StartsWith("String")))
{
if (oneName.Equals(twoName))
{
if (oneValue == null)
{
if (twoValue != null)
{
result = false;
break; //如果有不一样的就退出循环
}
}
else if (oneValue != null)
{
if (twoValue != null)
{
if (!oneValue.Equals(twoValue))
{
result = false;
break; //如果有不一样的就退出循环
}
}
else if (twoValue == null)
{
result = false;
break; //如果有不一样的就退出循环
}
}
}
else
{
result = false;
break;
}
}
else
{
//如果对象中的属性是实体类对象,递归遍历比较
bool b = CompareType(oneValue, twoValue);
if (!b) { result = b; break; }
}
}
return result;
}
//调用
private void btnOrder_Click(object sender, EventArgs e)
{
//实体类比较
UserVo userVoOne = new UserVo();
UserVo userVoTwo = new UserVo();
userVoOne.UserID = 1;
//userVoOne.UserAccount = "a";
userVoTwo.UserID = 1;
bool flag = CompareType(userVoOne, userVoTwo);
if (flag)
{
MessageBox.Show("两个类数据相同");
}
else
{
MessageBox.Show("两个类数据不相同");
}
}
设置软件开机启动
界面:
代码:
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 开机启动
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//获得应用程序路径
private string StrAssName = string.Empty;
//获得应用程序名
private string ShortFileName = string.Empty;
private void Form1_Load(object sender, EventArgs e)
{
}
//添加到开机启动
public void AddPowerBoot()
{
try
{
if(string.IsNullOrEmpty(ShortFileName) || string.IsNullOrEmpty(StrAssName))
{
MessageBox.Show("输入框不能为空");
return;
}
//此方法把启动项加载到注册表中
//获得应用程序路径
//string StrAssName = Application.StartupPath + @"\" + Application.ProductName + @".exe";
//获得应用程序名
//string ShortFileName = Application.ProductName;
//路径:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run
RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
if (rgkRun == null)
{
rgkRun = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
}
rgkRun.SetValue(ShortFileName, StrAssName);
MessageBox.Show("添加到注册表成功");
}
catch (Exception ex)
{
MessageBox.Show("执行错误:" + ex.Message);
}
}
//移除开机启动
public void RemovePowerBoot()
{
try
{
if (string.IsNullOrEmpty(ShortFileName) || string.IsNullOrEmpty(StrAssName))
{
MessageBox.Show("输入框不能为空");
return;
}
//此删除注册表中启动项
//获得应用程序名
//string ShortFileName = Application.ProductName;
RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
if (rgkRun == null)
{
rgkRun = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
}
rgkRun.DeleteValue(ShortFileName, false);
MessageBox.Show("移除注册表成功");
}
catch (Exception ex)
{
MessageBox.Show("执行错误:" + ex.Message);
}
}
//设置开机启动
private void Button_SetPowerBoot_Click(object sender, EventArgs e)
{
AddPowerBoot();
}
//移除开机启动
private void Button_RemovePowerBoot_Click(object sender, EventArgs e)
{
RemovePowerBoot();
}
//选择要操作的程序
private void Button_GetModuleFileName_Click(object sender, EventArgs e)
{
//创建对象
OpenFileDialog ofg = new OpenFileDialog();
//设置默认打开路径(绝对路径)
ofg.InitialDirectory = "C:\\Users\\Administrator\\Desktop";
//设置打开标题、后缀
ofg.Title = "请选择程序的exe文件";
ofg.Filter = "exe文件|*.exe";
string path = string.Empty;
if (ofg.ShowDialog() == DialogResult.OK)
{
//得到打开的文件路径(包括文件名)
path = ofg.FileName.ToString();
Console.WriteLine("打开文件路径是:" + path);
TextBox_GetModuleFileName.Text = path;
StrAssName = path;
string[] arr = path.Split('\\');
ShortFileName = arr[arr.Length - 1];
Label_ProgramName.Text = "应用程序名:" + ShortFileName;
}
else if (ofg.ShowDialog() == DialogResult.Cancel)
{
MessageBox.Show("未选择打开文件!");
}
}
}
}
程序一定要用管理员身份运行,否则会报错
end