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. c++ function和bind

    bind 定义在头文件 functional 里 template<typename _Func, typename... _BoundArgs> inline typename _Bin ...

  2. POJ 3608 凸包间最短距离(旋转卡壳)

    Bridge Across Islands Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11539   Accepted: ...

  3. Redis和Mecahe的简介

    Memcache介绍 概念:Memcache是一个高性能,分布式内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像.视频.文件以及数据库检索的结果等. ...

  4. W/System.err: at android.view.ViewConfiguration.get(ViewConfiguration.java:369)

    *11-09 11:48:38.558 13887-13900/? W/System.err: at android.view.WindowManagerGlobal.getWindowManager ...

  5. (C)spring boot读取自定义配置文件时乱码解决办法

    这是入门的第三天了,从简单的hello spring开始,已经慢慢接近web的样子.接下来当然是读取简单的对象属性了. 于是按照网上各位大神教的,简单写了个对象book,如上一篇(B),其他配置不需要 ...

  6. Python SimpleHTTPServer简单HTTP服务器

    搭建FTP,或者是搭建网络文件系统,这些方法都能够实现Linux的目录共享.但是FTP和网络文件系统的功能都过于强大,因此它们都有一些不够方便的地方.比如你想快速共享Linux系统的某个目录给整个项目 ...

  7. httpclient传参类型与响应参数接收

    https://blog.csdn.net/qq_26562641/article/details/72817457 https://blog.csdn.net/chenjf0221/article/ ...

  8. Wordpress 后台文章编辑区添加模板选择功能

    功能:后台编辑文章时,可以选择文章使用的模板,效果如下图: 操作步骤: <?php /** * Template Name: kbsingle full * Add by Ryan 3/18/2 ...

  9. crontab-用于设置周期性被执行的指令

    一个很好用的工具. 参考文章: [入门] http://baike.baidu.com/view/1229061.htm [进阶] http://blog.csdn.net/tianlesoftwar ...

  10. Android记事本开发04

    昨天: 显式intent 隐身intent 今天: intentFilter 问题: 无法直接预览布局文件的效果.