/// <summary> /// 短信发送 /// </summary> /// <param name="tel"></param> /// <param name="content"></param> /// <param name="res"></param> /// <returns></returns> public LocalErrCode SendMsg(string tel, string content, out CMPP_SUBMIT_RESP res, string spNumber = null) { if (spNumber == null) { spNumber = spPhoneNumber; } CMPP_SUBMIT[] subMsg = CreateSubmitMsg(serviceId, spId, spNumber, tel, content); //服务器响应 CMPPMsgBody_Base resp = null; LocalErrCode localRes = LocalErrCode.组件未启动; res = null; for (int i = 0; i < subMsg.Length; i++) { localRes = clien.Submit(subMsg[i], out resp); res = resp as CMPP_SUBMIT_RESP; if (localRes != LocalErrCode.成功 || res.Result != DeliverResult.正确) { break; } } return(localRes); }
public LocalErrCode Submit(CMPPMsgBody_Base sendMsg, bool waitResp = false) { CMPPMsgBody_Base result = null; return(Submit(sendMsg, out result, waitResp)); }
/// <summary> /// 发送消息(同步等待服务器响应) /// (0命令成功处理 -1组件未启动 -2通道不可用 -3生成下发数据时错误 -4命令超时 -5指令异常丢失 -6重复的命令序列号 -7返回值类型非期望) /// </summary> /// <returns>返回值errorCode</returns> public LocalErrCode Submit(CMPPMsgBody_Base sendMsg, out CMPPMsgBody_Base resp, bool waitResp = true) { int currentChannelSN = channelSN; //记录当前通道序列号 DateTime cmdSendTime; //处理命令超时 resp = null; //响应 if (waitResp) { //等待命令响应锁 if (!System.Threading.Monitor.TryEnter(waitRespLock, MaxTimeOut * 1000)) { return(LocalErrCode.命令超时); } //添加命令队列 if (!CmppCmdQueue.TryAdd(sendMsg.MyHead.Sequence_Id, null)) { return(LocalErrCode.重复的命令序列号);//重复的命令序列号 } } cmdSendTime = DateTime.Now; //组件未启动,不能处理操作指令 if (!runFlag) { return(LocalErrCode.组件未启动); } //判断通道是否可用,不可用进行绑定 if (!channelStateReady) { Bind(); } //false通道未建立 true通道已建立可以发送数据 if (!channelStateReady) { return(LocalErrCode.通道不可用);//通道不可用 } //信道建立 开心进行初始短信信息 byte[] data; //填充 data = sendMsg.WriteBytes(); //进行发送,然后判断是否有返回值 try { lock (channelLockFlag) { currentChannelSN = channelSN; client_sk.GetStream().Write(data, 0, data.Length); } } catch (Exception ex) { //写入操作失败,通道作废 移除命令 // CloseSoket(); WriteLog(ex.Message); if (waitResp) { CmppCmdQueue.TryRemove(sendMsg.MyHead.Sequence_Id, out resp); } return(LocalErrCode.通道不可用); } channelLastUpdate = DateTime.Now; if (waitResp) { LocalErrCode result = WaiteResp(cmdSendTime, currentChannelSN, (uint)sendMsg.MyHead.Command_Id, sendMsg.MyHead.Sequence_Id, out resp); Monitor.Exit(waitRespLock); return(result);// } return(LocalErrCode.成功); }
/// <summary> /// 等待响应 /// (循环取命令队列) /// </summary> /// <param name="cmdSendTime"></param> /// <param name="currentChannelSN"></param> /// <param name="cmdId"></param> /// <param name="cmdSequence"></param> /// <param name="resp"></param> /// <returns></returns> private LocalErrCode WaiteResp(DateTime cmdSendTime, int currentChannelSN, uint cmdId, uint cmdSequence, out CMPPMsgBody_Base resp) { //判断命令超时情况,判断通道序列号变更情况,判断命令存活情况 resp = null; do { //判断记录当前通道序列号 不等于构建通道的序列号 && 当前信道是否建立成功 if (currentChannelSN != channelSN && channelStateReady) { return(LocalErrCode.等待响应时通道已改变); break; } //CMPPMsgBody_Base tmp; //验证当前队列中是否含有序列号 if (!CmppCmdQueue.TryGetValue(cmdSequence, out resp)) { return(LocalErrCode.指令异常丢失);//指令异常丢失 break; } if (resp != null) { //判断是否为期望的返回值 if (((uint)resp.MyHead.Command_Id & 0x7fffffffU) == cmdId) { CmppCmdQueue.TryRemove(cmdSequence, out resp); return(LocalErrCode.成功); } else { return(LocalErrCode.返回值类型非期望);//返回值类型非期望 } //break; } Thread.Sleep(15);//每次进行15毫秒休眠 } //验证是否在期望时间内返回数据 while (cmdSendTime.AddSeconds(MaxTimeOut) > DateTime.Now && runFlag); return(LocalErrCode.命令超时); }
/// <summary> /// 读取失败或无可读数据返回 null /// </summary> /// <returns></returns> private CMPPMsgBody_Base read() { byte[] buffer; try { //判断是否有可用的数据 if (channelStateReady && client_sk != null && client_sk.Available > 0) { buffer = readBuffer(client_sk.GetStream()); } else { return(null);//没有可供读取的数据 } //将读取到的数据构建成对象 CMPPMsgHeader head; //读出头部,判断命令类型 head = CMPPMsgHeader.Read(buffer); //根据指令类型,构建应答对象,对于不处理的指令进行丢弃 CMPPMsgBody_Base data = null; switch (head.Command_Id) { case Command_Id.CMPP_SUBMIT_RESP: data = new CMPP_SUBMIT_RESP(head.Sequence_Id); break; case Command_Id.CMPP_DELIVER: data = new CMPP_DELIVER(head.Sequence_Id); break; case Command_Id.CMPP_ACTIVE_TEST: data = new CMPP_ACTIVE_TEST(head.Sequence_Id); break; case Command_Id.CMPP_ACTIVE_TEST_RESP: data = new CMPP_ACTIVE_TEST_RESP(head.Sequence_Id); break; case Command_Id.CMPP_TERMINATE: data = new CMPP_TERMINATE(head.Sequence_Id); break; case Command_Id.CMPP_TERMINATERESP: data = new CMPP_TERMINATE_RESP(head.Sequence_Id); break; default: break; } if (data != null) { data.ReadBytes(buffer); } return(data); } catch (Exception)//流读取异常 { CloseSoket(); return(null); } }
/// <summary> /// 后台读取线程 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void bWorker_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker bw = sender as BackgroundWorker; //处理过程 while (!bw.CancellationPending) { //判断通道是否可用 if (channelStateReady) { //从通道中读取数据对象,若返回值为null 则表示无数据或读取出错(读取出错处理在 read方法进行处理) CMPPMsgBody_Base data = read(); if (data != null) { channelLastUpdate = DateTime.Now; //对读取到的数据进行处理 switch (data.MyHead.Command_Id) { #region 命令响应 case Command_Id.CMPP_SUBMIT_RESP: case Command_Id.CMPP_ACTIVE_TEST_RESP: if (CmppCmdQueue.ContainsKey(data.MyHead.Sequence_Id)) { CmppCmdQueue[data.MyHead.Sequence_Id] = data; } break; #endregion #region 状态回报 上行 case Command_Id.CMPP_DELIVER: ThreadPool.QueueUserWorkItem(ThreadPoolExcuteFuctione, data); //响应服务器 CMPP_DELIVER deliver = data as CMPP_DELIVER; CMPP_DELIVER_RESP deliverResp = new CMPP_DELIVER_RESP(deliver.MyHead.Sequence_Id, deliver.Msg_Id, (uint)DeliverResult.正确); Submit(deliverResp); break; #endregion #region 拆除连接 case Command_Id.CMPP_TERMINATE: Submit(new CMPP_TERMINATE_RESP(data.MyHead.Sequence_Id)); CloseSoket(); break; #endregion #region 连接检测 case Command_Id.CMPP_ACTIVE_TEST: Submit(new CMPP_ACTIVE_TEST_RESP(data.MyHead.Sequence_Id)); break; #endregion default: //未知的命令丢弃 break; } } } //判断通道空闲时间间隔,进行超时处理 if (channelLastUpdate.AddSeconds(ActiveTestInterval) < DateTime.Now) { var err = Submit(new CMPP_ACTIVE_TEST());// if (err != LocalErrCode.成功) { channelLastUpdate = channelLastUpdate.AddSeconds(ActiveTestInterval);//n秒后重试 防止过多发送 WriteLog("长连接链路检测发送失败:" + err.ToString()); } } Thread.Sleep(10);//每个周期休眠10毫秒 } }