using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using DBContext; namespace WatchServer { public static class OnLineUserCollection {
private static IList<EngineUser> _onlineUserList;
public static int Count { get { return OnlineUserList.Count; } } public static IList<EngineUser> OnlineUserList {
get { return _onlineUserList ?? (_onlineUserList = new List<EngineUser>()); }
set { _onlineUserList = value; }
}
} interface IEngineUser {
void SendMessage(String message);
} public class EngineUser : IEngineUser {
public string watchId = "Anonymous";
public TcpClient Client;
public StreamWriter Sw;
public StreamReader Sr;
public bool Active { get { return this.Client.Connected; } }
public EngineUser(TcpClient client) {
this.Client = client;
NetworkStream netStream = client.GetStream();
Sw = new StreamWriter(netStream, Encoding.UTF8);
Sr = new StreamReader(netStream, Encoding.UTF8);
} public void SendMessage(String message) {
if (Sw != null) { Sw.WriteLine(message); Sw.Flush(); }
}
} public class AnalysizeEngine : IDisposable {
#region 多线程 singleton private static AnalysizeEngine _instance;
private static readonly object LockObject = new object(); public static AnalysizeEngine GetInstance() {
if (_instance == null) {
lock (LockObject) {
if (_instance == null) _instance = new AnalysizeEngine();
}
}
return _instance;
}
#endregion #region 私有变量 将engine中的线程全部用变量声明,保存在这里,退出的时候,要全部结束!
private TcpListener _listener;
//todo:up not implemented
#endregion #region 构造函数
private AnalysizeEngine()
: this("tcp engine") {
}
private AnalysizeEngine(String name) { }
#endregion #region 属性事件
public event HandleOverActionHandler Handle;
public delegate void HandleOverActionHandler(String message); public event Action<String> OnDisconnect;
#endregion #region 成员方法
private IPAddress ResolveIp(IPAddress[] addrIP) {
var ipAddressRegex = new Regex(@"((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))))");
IPAddress returnValue = null;
addrIP.ToList().ForEach(t => {
if (returnValue == null)
returnValue = ipAddressRegex.IsMatch(t.ToString()) ? t : null; });
returnValue = returnValue ?? IPAddress.Parse(ConfigHelper.Get("localIp"));
return returnValue;
}
#endregion #region 操作方法 public AnalysizeEngine Start() {
IPAddress ip = ResolveIp(Dns.GetHostAddresses(Dns.GetHostName()));
try {
if (_listener == null)
_listener = new TcpListener(ip,
Int32.Parse(ConfigHelper.Get("localPort")));
_listener.Start();
} catch (Exception ex) {
LogHelper.Error(ex);
}
var mainTask = Task.Factory.StartNew(() => GetInstance().Process());
var msgDistributeTask = Task.Factory.StartNew(() => GetInstance().DistributeMessage());
return this;
} private void DistributeMessage() {
while (true) {
try {
if (OnLineUserCollection.OnlineUserList.Count <= 0) break;
OnLineUserCollection.OnlineUserList.ToList().ForEach(a => {
var commandsToSend = GetCommandsToSendByWatchId(a.watchId);
if (commandsToSend.Count > 0) commandsToSend.ForEach(b => {
a.SendMessage(b.CommandText);
b.ExecuteResult =
(int)
WatchCommandExecuteEnum
.ExecuteSuccess; using (var context = DataContext.Context) {
context.Attach(b);
context.ObjectStateManager.ChangeObjectState(b, EntityState.Modified);
//refresh online status
context.W_User.Select(e => e.WatchId).ToList().ForEach(c => { UserOnlineStatus status = OnLineUserCollection.OnlineUserList.Select(d => d.watchId).ToArray().Contains(c)
? UserOnlineStatus.Online : UserOnlineStatus.Offline;
SetWatchStatusByWatchId(c, status);
}); context.SaveChanges();
}
//UpdateWatchOnlineStatusByWatchId(a.watchId);
});
}); Thread.Sleep(5000);
} catch (Exception ex) {
LogHelper.Error(ex);
}
}
} /// <summary>
/// when command is sent,ie reboot or shutoff,update alternate status ,alternative states are not implied yet.
/// </summary>
/// <param name="watchId"></param>
private void UpdateWatchOnlineStatusByWatchId(string watchId) {
var watchStatus = (int)UserOnlineStatus.Offline;
using (var context = DataContext.Context) {
IList<W_LocationData> commandList = context.W_LocationData.Top("2").Where(a => a.WatchId == watchId).ToList();
var watch = context.W_User.First(a => a.WatchId == watchId);
if (watch == null) throw new Exception("cannot find specified watchid,watch id null"); }
} private List<W_Command> GetCommandsToSendByWatchId(string watchId) {
using (var context = DataContext.Context) {
IEnumerable<W_Command> commands =
context.W_Command.Where(
a => a.WatchId == watchId && a.ExecuteResult == (int)WatchCommandExecuteEnum.NotExecuted
);
return commands.ToList();
}
}
public void Process() {
while (true) {
TcpClient guest;
try {
guest = _listener.AcceptTcpClient();
EngineUser u = new EngineUser(guest); Task.Factory.StartNew(f => {
EngineUser client = f as EngineUser;
if (client == null) return;
while (client != null && client.Active) {
try {
if (client.Client.GetStream().CanRead) {
string receiveString = "";
byte[] buffer = new byte[int.Parse(ConfigHelper.Get("bufferSize"))]; int i = client.Client.GetStream().Read(buffer, 0, buffer.Length);
receiveString = Encoding.UTF8.GetString(buffer, 0, i); if (!client.Client.GetStream().DataAvailable) {
if (receiveString == "exit") break;
if (this.Handle != null && receiveString != "")
Handle(receiveString);
if (receiveString != "") {
var analysizer = new ReceiveDataAnalysizer(receiveString);
analysizer.Analysize();
client.watchId = analysizer.AnalysizeResult;
if (!string.IsNullOrEmpty(client.watchId)) {
LogHelper.Info(
OnLineUserCollection.OnlineUserList.Any(
a => a.watchId == client.watchId)
? DateTime.Now + client.watchId + "conneted"
: null);
SetWatchStatusByWatchId(client.watchId, UserOnlineStatus.Online);
OnLineUserCollection.OnlineUserList.Add(OnLineUserCollection
.OnlineUserList.Any(
a => a.watchId == client.watchId)
? null
: u);
}
}
if (receiveString == "") {
OnLineUserCollection.OnlineUserList.Remove(client);
LogHelper.Info(client.watchId + " disconnected");
SetWatchStatusByWatchId(client.watchId, UserOnlineStatus.Offline);
if (OnDisconnect != null)
OnDisconnect(client.watchId);
break;
}
}
}
} catch (Exception ex) {
LogHelper.Error(ex);
}
}
}, u);
} catch { break; } }
} private static void SetWatchStatusByWatchId(String watchId, UserOnlineStatus status) {
using (var context = DataContext.Context) {
var model = context.W_User.FirstOrDefault(a => a.WatchId == watchId);
if (model != null)
model.Status = (int)status;
context.SaveChanges();
}
} public AnalysizeEngine Stop() {
//here we close all online connections
if (OnLineUserCollection.OnlineUserList.Count > 0)
OnLineUserCollection.OnlineUserList.ToList().ForEach(t => { if (t.Client != null && t.Active) t.Client.Close(); });
if (Handle != null)
Handle.GetInvocationList().ToList().ForEach(a => {
Handle -= a as HandleOverActionHandler;
});
if (OnDisconnect != null)
OnDisconnect.GetInvocationList().ToList().ForEach(a => {
OnDisconnect -= a as Action<string>;
});
if (_listener != null)
_listener.Stop();
return this;
}
#endregion #region IDisposable 成员 public void Dispose() {
Handle = null;
OnDisconnect = null;
_listener.Stop();
_instance = null;
_listener = null;
}
#endregion
}
}

c# tcplistener 与 client通信 服务端 今天写一下的更多相关文章

  1. 警察与小偷的实现之中的一个client与服务端通信

    来源于ISCC 2012 破解关第四题 目的是通过逆向police.实现一个thief,可以与police进行通信 实际上就是一个RSA加密通信的样例,我们通过自己编写client和服务端来实现上面的 ...

  2. Android BLE与终端通信(三)——client与服务端通信过程以及实现数据通信

    Android BLE与终端通信(三)--client与服务端通信过程以及实现数据通信 前面的终究仅仅是小知识点.上不了台面,也仅仅能算是起到一个科普的作用.而同步到实际的开发上去,今天就来延续前两篇 ...

  3. TCP通信服务端及客户端代码

    Java TCP通信使用的是Socket(客服端)和ServerSocket(服务端),具体代码如下. server端代码: import java.io.BufferedReader; import ...

  4. java TCP 通信:服务端与客服端

    1.首先先来看下基于TCP协议Socket服务端和客户端的通信模型: Socket通信步骤:(简单分为4步) 1.建立服务端ServerSocket和客户端Socket 2.打开连接到Socket的输 ...

  5. java UDP 通信:服务端与客服端

    import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import j ...

  6. Socket通信-服务端

    WSADATA wsd; SOCKET sClient; SOCKET sServer; SOCKADDR_IN addrServ; char chRcvBuf[RECV_BUF_SIZE]; if ...

  7. C# Socket服务端与客户端通信(包含大文件的断点传输)

    步骤: 一.服务端的建立 1.服务端的项目建立以及页面布局 2.各功能按键的事件代码 1)传输类型说明以及全局变量 2)Socket通信服务端具体步骤:   (1)建立一个Socket   (2)接收 ...

  8. grpc(3):使用 golang 开发 grpc 服务端和client

    1,关于grpc-go golang 能够能够做grpc的服务端和client. 官网的文档: http://www.grpc.io/docs/quickstart/go.html https://g ...

  9. JAVA学习第六十三课 — 关于client服务端 &amp;&amp; URL类 &amp; URLConnection

    常见的client和服务端 client:       浏览器:IE:弹窗体,猎豹:弹窗体.多标签,争强效果 服务端:       server:TomCat:1.处理请求 2.给予应答 想让TomC ...

随机推荐

  1. 深入理解restfulAPI和 Oauth2.0(精简版)

    一.restfulAPI 1.解释: restfulAPI协议,我们也可以说是一套API接口编写风格. 它被现在很多企业所认可和默认,是一套成俗的API接口编写方案. 2.restfulAPI之资源 ...

  2. JavaSE 第二次学习随笔(作业一)

    package homework2; import java.io.ObjectInputStream.GetField; import java.util.Arrays; public class ...

  3. PLC状态机编程第四篇-历史状态处理

    今天我们接着上次的控制任务,加入历史状态,这个任务会比较复杂,象这样的任务我们倾向于自动生成PLC程序,自己写容易出错.但为了演示,我们可以尝试一下.言归正传,下面是我们的控制任务. 控制任务 这次的 ...

  4. python pycharm2018开启debug模式

    为什么需要开启DEBUG模式1.如果开启了DEBUG模式,那么在代码中如果抛出了异常,在浏览器的页面中可以看到具体的错误信息,以及具体的错误代码位置,方便开发者调试.2.如果开启DEBUG模式,那么以 ...

  5. Codeforces Round #462 (Div. 2) C DP

    C. A Twisty Movement time limit per test 1 second memory limit per test 256 megabytes input standard ...

  6. eclipse包名分层级显示

    eclipse包名像文件列表那样显示设置方法

  7. laravel5.5事件广播系统

    目录 1. 定义广播事件 1.1 广播名称 1.2 广播数据 1.3 广播队列 1.4 广播条件 2. 频道授权 2.1 定义授权路由 2.2 定义授权回调 3. 对事件进行广播 3.1 可以使用ev ...

  8. 容器技术的落地还要依靠SDN

    容器能够实现新应用程序的快速部署,代表着目前IT开发社区的最热门趋势之一.然而,想要实现容器部署生产环境,IT人员还需要使用SDN技术,在分布式微应用程序之间实现可扩展.可管理且安全的通信. 什么是容 ...

  9. 《Cracking the Coding Interview》——第12章:测试——题目1

    2014-04-24 23:10 题目:找出下面代码里的错误. 解法:请看下面. 代码: // 12.1 What's wrong with the following code segment? # ...

  10. HTML DOM简易学习笔记

    文字版:https://github.com/songzhenhua/github/blob/master/HTML DOM简易学习笔记.txt 学习地址:http://www.w3school.co ...