时间:01:48:59 来源:陶晶莹 作者:蜘蛛亚博提现规则 点击:58
{随机段子}

游客抠走故宫石子_GPS服务端(上)-Socket服务端(golang)

 从第一次写GPS的服务端到现在,已经过去了八年时光。一直是用.net修修改改,从自己写的socket服务,到suppersocket,都是勉强在坚持着,没有真正的稳定过。

  最近一段时间,服务端又出了两个问题:

  1、UDP服务:System.Net.Sockets.SocketException (0x80004005): 当该操作在进行中,由于保持活动的操作检测到一个故障,该连接中断。

  2、数据库操作:System.Data.SqlClient.SqlException (0x80131904): 事务(进程 ID 54)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。

  第一点估计真的是.net socket框架的问题,尝试过网上搜索的解决方案都没有解决,同样的程序在另外一台服务器正常,唯独其中一台隔三差五的就出现这个问题 。以下是服务端部分代码:

   di yi dian gu ji zhen de shi. net socket kuang jia de wen ti, chang shi guo wang shang sou suo de jie jue fang an dou mei you jie jue, tong yang de cheng xu zai ling wai yi tai fu wu qi zheng chang, wei du qi zhong yi tai ge san cha wu de jiu chu xian zhe ge wen ti . yi xia shi fu wu duan bu fen dai ma:

 1      /// 
 2         /// 初始化监听
 3         /// 
 4         private void InitServer()
 5         {
 6             server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
 7             uint IOC_IN = 0x80000000;
 8             uint IOC_VENDOR = 0x18000000;
 9             uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
10             server.IOControl((int)SIO_UDP_CONNRESET, new Byte[] { Convert.ToByte(false) }, null);//不知道这句有没有用。
11             string hostName = Dns.GetHostName();   //获取本机名
12             IPHostEntry localhost = Dns.GetHostEntry(hostName);
13             IPAddress[] ips = localhost.AddressList;
14             IPAddress localaddr = null;
15             foreach (IPAddress ip in ips)
16             {
17                 if (ip.IsIPv6LinkLocal || ip.IsIPv6Teredo)
18                 {
19                     continue;
20                 }
21                 localaddr = ip;
22             }
23 
24             state = new State(server);
25             server.Bind(new IPEndPoint(localaddr, _config.Port));
26             server.BeginReceiveFrom(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, ref state.RemoteEP, new AsyncCallback(ReceiveCallBack), state);
27         }
 1   private void ReceiveCallBack(IAsyncResult ar)
 2         {
 3             try
 4             {
 5                 State _state = ar.AsyncState as State;
 6                 int size = server.EndReceiveFrom(ar, ref _state.RemoteEP);
 7                 if (size > 0)
 8                 {
 9                     byte[] data = new byte[size];
10                     Array.Copy(_state.Buffer, 0, data, 0, size);
11                     var session = AddClient(_state.RemoteEP, data);
12                     if (session != null)
13                     {
14                         _state.Session = session;
15                     }
16                     OnReceived?.Invoke(_state.Session, data);
17                     server.BeginReceiveFrom(_state.Buffer, 0, _state.Buffer.Length, 0, ref _state.RemoteEP, new AsyncCallback(ReceiveCallBack), _state);
18                 }
19                 else
20                 {
21                     LogHelper.Error("size<=0");
22                     _state = ar.AsyncState as State;
23                     server.BeginReceiveFrom(_state.Buffer, 0, _state.Buffer.Length, SocketFlags.None, ref _state.RemoteEP, new AsyncCallback(ReceiveCallBack), _state);
24                     //Dispose();
25                     //SessionClosed?.Invoke(_state.Session);
26                 }
27             }
28             catch (SocketException ex)
29             {
30                 LogHelper.Error(ex.ToString());//此处报错
31                 try
32                 {
33                     Dispose();
34                     InitServer();
35                 }
36                 catch (Exception e)
37                 {
38                     LogHelper.Error($"重启时报错{e.ToString()}");
39                 }
41             }
42         }

  而第二点数据库的操作,则是设计缺陷了,四个端口接收不同协议的终端数据,定时5秒批量写入历史数据表和批量update一张最新数据的表,这张最新数据表还有前端在定时select。

  时不时的深更半夜接到客户电话要求处理,也是心累了,因此,想尝试一下用golang+MQ+.net的解决方案,试图彻底解决以上烦恼。成功与否那是后话,先要有所尝试嘛。

  架构图:

?

  这种设计可能存在的风险:Socket Server写入MQ Server的速度如果大于MQ Clients到SqlServer的速度,会导致数据延时,最主要服务器内存受不了。系统需求又不允许MQ消费者丢弃任何数据。

  没关系,我们先假设处理速度能快于接收速度,否则生活没法继续,哈哈。

  先上一段golang服务端代码

package main

import (
    "fmt"
    "net"
    "time"
    "configmanager"
    "logger"
)
func checkError(err error){
    if err != nil {
        fmt.Println(err)
    }
}
func clientHandle(conn *net.UDPConn) {
    var buf [512]byte
    size, addr, err := conn.ReadFromUDP(buf[0:])
    if err != nil {
        logger.Error.Println(err)
        return
    }
    
    daytime :=time.Now().Format("2006-01-02 15:04:05");
    var buff =buf[0:size]
    logger.Info.Printf("%x
",buff)//此处先打印,下篇写入MQ
    conn.WriteToUDP([]byte(daytime), addr)
}
func main(){
    configmanager.Initialize()//初始化配置文件处理包,将配置config.ini写入到全局映射AppSettings中
    port := configmanager.AppSettings["port"]
    logger.Info.Print("开始在" + port + "监听
")
    udpaddr,err:=net.ResolveUDPAddr("udp4",":" + port)
    checkError(err)
    udpconn,err := net.ListenUDP("udp",udpaddr)
    checkError(err)
    for{
        clientHandle(udpconn);
    }
}

打开编译后的应用程序,同时打开TcpUdp压测工具

以上,golang的UDP服务端就成功了,下一篇再要看看golang是怎么操作rabbitmq的

当前文章:http://www.honghiem.com/l7vwl7s/35756-266468-90538.html

发布时间:01:03:25

王中王论坛??藏宝图论坛高清跑狗图??香港现场报码??香港挂牌玄机??www.277118.com??综合挂牌??手机报码??今晚开什么码结果??www.8555310.com??平特肖走势图??

本文标签: 非洲客天安门中暑 越野车碾压藏羚羊 松原棕永值幼儿园

回到顶部