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. PHP的IMAP函数

    imap_8bit -转换的8位字符串的引用,打印字符串 imap_alerts -返回所有的I MAP邮件警报已经发生 imap_append -附加了一系列的信息到指定邮箱 imap_base64 ...

  2. 477. Total Hamming Distance

    class Solution { public: int totalHammingDistance(vector<int>& nums) { ; ; i < ; i++) { ...

  3. Teaching Is a Fruitful Way to Learn【教学是一种有效的学习方式】

    Teaching Is a Fruitful Way to Learn For thousands of years, people have known that the best way to u ...

  4. mysql学习第二天函数

    -- 1.绝对值 select abs(-1)from dual -- 2.求平方根select sqrt(6)from dual -- 3.圆周率select pi()from dual -- 4. ...

  5. PHP.19-验证码生成

    生成验证码 思路:先定义验证码函数getCode() //绘制验证码 $num = 4; //字符长度 getCode($num, 2); 1.创建画布,分配颜色 imagecreatetruecol ...

  6. Sql Server多种分页性能的比较

    一.前言 因为工作关系,遇到了非常大的数据量的分页问题,数据总共有8000万吧,这个显然不是简单的分页能够解决的,需要从多多方面考虑,从分表.分库等等.但是这个也让我考虑到了分页性能的问题,在不同数据 ...

  7. svn git 导入本地文件到远程服务器 import

    以前,想要把本地的一个文件上传到svn 或者git 服务器的时候,都要先把服务器上的文件夹down 下来,然后把要添加的文件添加进去,然后提交. 想想都麻烦. 现在我们用import 命令就可以做到, ...

  8. centos 6.X 关闭selinux

    SELinux(Security-Enhanced Linux) 是美国国家安全局(NSA)对于强制访问控制的实现,是 Linux历史上最杰出的新安全子系统.在这种访问控制体系的限制下,进程只能访问那 ...

  9. 一个python的文件对比脚本

    脚本主要用来给游戏客户端做热更的. 处理方式就是针对每个文件求其MD5值,再根据文件的目录和名字对比两个版本的MD5值,如果不一样,则这次热更就需要更新这个文件. 用法很简单. 1,生成MD5码列表 ...

  10. python学习笔记三:函数及变量作用域

    一.定义 def functionName([arg1,arg2,...]): code 二.示例 #!/usr/bin/python #coding:utf8 #coding=utf8 #encod ...