GPS服务端(上)-Socket服务端(golang)
从第一次写GPS的服务端到现在,已经过去了八年时光。一直是用.net修修改改,从自己写的socket服务,到suppersocket,都是勉强在坚持着,没有真正的稳定过。
最近一段时间,服务端又出了两个问题:
1、UDP服务:System.Net.Sockets.SocketException (0x80004005): 当该操作在进行中,由于保持活动的操作检测到一个故障,该连接中断。
2、数据库操作:System.Data.SqlClient.SqlException (0x80131904): 事务(进程 ID 54)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。
第一点估计真的是.net socket框架的问题,尝试过网上搜索的解决方案都没有解决,同样的程序在另外一台服务器正常,唯独其中一台隔三差五的就出现这个问题 。以下是服务端部分代码:
/// <summary>
/// 初始化监听
/// </summary>
private void InitServer()
{
server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
uint IOC_IN = 0x80000000;
uint IOC_VENDOR = 0x18000000;
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | ;
server.IOControl((int)SIO_UDP_CONNRESET, new Byte[] { Convert.ToByte(false) }, null);//不知道这句有没有用。
string hostName = Dns.GetHostName(); //获取本机名
IPHostEntry localhost = Dns.GetHostEntry(hostName);
IPAddress[] ips = localhost.AddressList;
IPAddress localaddr = null;
foreach (IPAddress ip in ips)
{
if (ip.IsIPv6LinkLocal || ip.IsIPv6Teredo)
{
continue;
}
localaddr = ip;
} state = new State(server);
server.Bind(new IPEndPoint(localaddr, _config.Port));
server.BeginReceiveFrom(state.Buffer, , state.Buffer.Length, SocketFlags.None, ref state.RemoteEP, new AsyncCallback(ReceiveCallBack), state);
}
private void ReceiveCallBack(IAsyncResult ar)
{
try
{
State _state = ar.AsyncState as State;
int size = server.EndReceiveFrom(ar, ref _state.RemoteEP);
if (size > )
{
byte[] data = new byte[size];
Array.Copy(_state.Buffer, , data, , size);
var session = AddClient(_state.RemoteEP, data);
if (session != null)
{
_state.Session = session;
}
OnReceived?.Invoke(_state.Session, data);
server.BeginReceiveFrom(_state.Buffer, , _state.Buffer.Length, , ref _state.RemoteEP, new AsyncCallback(ReceiveCallBack), _state);
}
else
{
LogHelper.Error("size<=0");
_state = ar.AsyncState as State;
server.BeginReceiveFrom(_state.Buffer, , _state.Buffer.Length, SocketFlags.None, ref _state.RemoteEP, new AsyncCallback(ReceiveCallBack), _state);
//Dispose();
//SessionClosed?.Invoke(_state.Session);
}
}
catch (SocketException ex)
{
LogHelper.Error(ex.ToString());//此处报错
try
{
Dispose();
InitServer();
}
catch (Exception e)
{
LogHelper.Error($"重启时报错{e.ToString()}");
}
}
}
而第二点数据库的操作,则是设计缺陷了,四个端口接收不同协议的终端数据,定时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 []byte
size, addr, err := conn.ReadFromUDP(buf[:])
if err != nil {
logger.Error.Println(err)
return
} daytime :=time.Now().Format("2006-01-02 15:04:05");
var buff =buf[:size]
logger.Info.Printf("%x\r\n",buff)//此处先打印,下篇写入MQ
conn.WriteToUDP([]byte(daytime), addr)
}
func main(){
configmanager.Initialize()//初始化配置文件处理包,将配置config.ini写入到全局映射AppSettings中
port := configmanager.AppSettings["port"]
logger.Info.Print("开始在" + port + "监听\r\n")
udpaddr,err:=net.ResolveUDPAddr("udp4",":" + port)
checkError(err)
udpconn,err := net.ListenUDP("udp",udpaddr)
checkError(err)
for{
clientHandle(udpconn);
}
}
打开编译后的应用程序,同时打开TcpUdp压测工具



以上,golang的UDP服务端就成功了,下一篇再要看看golang是怎么操作rabbitmq的
GPS服务端(上)-Socket服务端(golang)的更多相关文章
- 记一次阿里云oss文件上传服务假死
引言 记得以前刚开始学习web项目的时候,经常涉及到需要上传图片啥的,那时候都是把图片上传到当前项目文件夹下面,每次项目一重启图片就丢了.虽然可以通过修改/tomcat/conf/server.xml ...
- Chris Richardson微服务翻译:微服务架构中的服务发现
Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现(本文) 微服务之事件驱动的数据管理 微服 ...
- MSDN上的异步socket 服务端例子
MSDN上的异步socket 服务端例子 2006-11-22 17:12:01| 分类: 代码学习 | 标签: |字号大中小 订阅 Imports SystemImports Syste ...
- C# TCP socket发送大数据包时,接收端和发送端数据不一致 服务端接收Receive不完全
简单的c# TCP通讯(TcpListener) C# 的TCP Socket (同步方式) C# 的TCP Socket (异步方式) C# 的tcp Socket设置自定义超时时间 C# TCP ...
- 在python中编写socket服务端模块(二):使用poll或epoll
在linux上编写socket服务端程序一般可以用select.poll.epoll三种方式,本文主要介绍使用poll和epoll编写socket服务端模块. 使用poll方式的服务器端程序代码: i ...
- AutoCAD.net支持后台线程-Socket服务端
最近因为公司项目的需求,CAD作为服务端在服务器中常驻运行,等待客户端远程发送执行任务的指令,最终确认用Socket-tcp通讯,CAD需要实时监听客户端发送的消息,这时就需要开启线程执行Socket ...
- 基于netty的socket服务端触发了channelInactive方法,但实际连接没有断开的问题
背景: 一个中小型H5游戏,后端使用基于 netty 的socket服务 服务端 分为 分发服务器 & 业务服务器,业务服务器可负载 用户客户端与分发服务器连接 分发服务器再作为客户端与每台业 ...
- TCP客户端图片上传服务端保存本地示例
//TCP客户端public class TCPClient { public static void main(String[] args)throws IOException { Socket s ...
- 关于调试php的socket服务端中遇到的问题及解决办法
今天终于把socket的服务端解决了,期间遇到了很多问题呢~ 1.用cmd运行php的问题: 2.socket_create()函数未定义问题: 3.查看端口的问题. 以下逐一说说解决办法: 1.在c ...
随机推荐
- linux HAProxy及Keepalived热备
HAProxy 它是免费,快速且可靠的一种解决方案没,适用于那些负载特大的web站点这些站点通常又需要会话保持或七层处理提供高可用性,负载均衡及基于tcp和http应用的代理 衡量负载均衡器性能的因素 ...
- 2_成员函数(Member Functions)
成员函数以定从属于类,不能独立存在,这是它与普通函数的重要区别.所以我们在类定义体外定义成员函数的时候,必须在函数名之前冠以类名,如Date::isLeapYear().但如果在类定义体内定义成员函数 ...
- ARM架构
ARM架构(过去称作进阶精简指令集机器(Advanced RISC Machine),更早称作Acorn RISC Machine)是一个32位元精简指令集(RISC) 中央处理器(processor ...
- JAVA代码发送邮件示例和解释(二)
之前有使用过一次在程序中发邮件的功能,也写了一篇相关的笔记,当时使用的是163邮箱,经过测试多个163账号都是可行的.但是最近把账号换成中国移动@chinamobilesz.com这种结尾的时候,却一 ...
- python3.4 UnicodeDecodeError: 'gbk' codec can't decode byte 0xff in position
python3.4 UnicodeDecodeError: 'gbk' codec can't decode byte 0xff in position 实用python的时候 打开一个csv的文件出 ...
- E: 无法获得锁 /var/lib/apt/lists/lock - open (11: 资源暂时不可用)
1 错误描述 youhaidong@youhaidong:~$ sudo apt-get update E: 无法获得锁 /var/lib/apt/lists/lock - open (11: 资源暂 ...
- hdu5923 Prediction
jxt的思路 先膜一发 先处理 T这棵树上每个点到祖先这条链的点所生成的并查集 每个点的并查集都得分开来存 这个dfs做就好了 最后询问的时候 将k 个点的并查集合并就是这个询问的连通图 易得答案 # ...
- studio设置File Templates
从项目的整体风格考虑,对所有类要进行必要的说明,就注释说明来说首先需要说明是作者,文件创建时间,业务功能说明,这几项是基本的内容,而添加这些说明内容以前可能手动的添加文件标题头,这种做法现在都非常过时 ...
- 版本控制工具--svn和git的使用(一) -----版本控制的好处以及分类
版本控制工具 版本控制VCS(Version Control Systems)是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统.这个系统可以自动帮我们备份文件的每一次更改,并且可以 ...
- 获取MySql每一列的数据类型和长度默认值等信息
如何获取MySql表中各个列的数据类型? show columns from tablename 返回结果如下: id int(11) NO PRI auto_incr ...