/// <summary> /// 服务端主动端口调用的方法 /// </summary> /// <param name="fd"></param> /// <returns></returns> public void Close(int conn) { try { //放入连接已经断开的队列 if (!ShutdownHand.TryAdd(conn, conn)) { Console.WriteLine("向连接断开队列添加数据失败!"); } //清空粘包区域 ClearBag(conn); int temp = LSocket.close(conn); //关闭连接 if (temp == -1) { //失败写日志 Console.WriteLine("主动关闭socket失败-1:" + conn.ToString()); } } catch (Exception ex)//异常写日志 { Console.WriteLine("关闭socket异常:" + ex.ToString()); } }
/// <summary> /// 断开比较重要,可能需要业务通知,再封装一层调用 /// </summary> /// <param name="fd"></param> /// <returns></returns> private void SocketClose(int conn) { try { //放入连接已经断开的队列 if (!ShutdownHand.TryAdd(conn, conn)) { Console.WriteLine("向连接断开队列添加数据失败!"); } //清空粘包区域 ClearBag(conn); //执行事件通知 if (SocketCloseCall != null) { SocketCloseCall(conn);//通知业务层,哪一个连接断开了 } int temp = LSocket.close(conn); //关闭连接 if (temp == -1) { //失败写日志 Console.WriteLine("关闭socket失败-1:" + conn.ToString()); } } catch (Exception ex)//异常写日志 { Console.WriteLine("关闭socket异常:" + ex.ToString()); } }
/// <summary>/// 根据文件句柄发送消息 /// </summary> /// <param name="fid">文件句柄</param> /// <param name="mes">消息</param> public void SendMessage(int fid, string messtr) { byte[] mes = WrapNewByteArr(messtr); try { while (true) { System.IntPtr r = Marshal.UnsafeAddrOfPinnedArrayElement <byte>(mes, 0); if (ShutdownHand.ContainsKey(fid))//当前消息舍弃 { Console.WriteLine("链接以已经断开,消息舍弃:" + fid); return; } int tempsent = LSocket.send(fid, r, mes.Length, 0); if (tempsent == mes.Length)//发送完毕 { //Console.WriteLine("发送完成:" + tempsent); break; } else if (tempsent > 0 & tempsent < mes.Length)//没有发送完毕 { int tempindexLent = mes.Length - tempsent; byte[] bytesenttemp = new byte[tempindexLent]; for (int i = 0; i < tempindexLent; i++) { bytesenttemp[i] = mes[tempsent + i]; } mes = bytesenttemp; // Console.WriteLine("中间发送:" + tempsent); } else if (tempsent == -1)//没有准备好 { // Console.WriteLine("发送:" + tempsent); } else { Console.WriteLine("发送数据异常" + fid); } } } catch (Exception ex) { Console.WriteLine("Send消息异常:标识为:" + fid + ex.Message); } }
/// <summary>/// Epoll的回调 /// </summary> /// <param name="fidret"></param> private void CSCallbackFunction(int fidret) { try { if (fidret == sockfd)//// 客户端有新的连接请求 { int conn = -1; sockaddr_in client_addr = new sockaddr_in(); int length = 16; conn = LSocket.accept(sockfd, ref client_addr, ref length); if (conn >= 0) { //清空缓冲区 ClearBag(conn); #region 设置no-block var setblock = LSocket.SetNoBlock(conn); if (setblock < 0)//失败 { Console.WriteLine("设置bolk失败:标识为:" + conn + "," + setblock); } else { Console.WriteLine("设置bolk成功:标识为:" + conn + ",返回值为" + setblock); } #endregion // 向epoll注册client_sockfd监听事件 #region 向epoll注册client_sockfd监听事件 var epollctlretclient = LSocket.epoll_ctl_ADD(epoll_fd, EPOLL_CTL.EPOLL_CTL_ADD, conn, (int)EpollEvents.EPOLLIN); if (epollctlretclient == -1) { Console.WriteLine("epoll_ctl客户端-1: {0}", epollctlretclient.ToString()); } else { int outint = 0; //移除等待关闭的句柄 ShutdownHand.TryRemove(conn, out outint); try { AcceptCall(conn); } catch (Exception exppp) { Console.WriteLine("调用AcceptCall委托异常:" + exppp.Message); } } #endregion } else { Console.WriteLine("有客户端接入失败:标识为:" + conn); } } else//有消息啦 { var epollctlretclient = LSocket.epoll_ctl_ADD(epoll_fd, EPOLL_CTL.EPOLL_CTL_DEL, fidret, (int)EpollEvents.EPOLLIN); if (epollctlretclient == -1) { Console.WriteLine("epoll_ctl删除监听失败-1: {0}", epollctlretclient.ToString()); } else { // Console.WriteLine("epoll_ctl删除成功"); switch (fidret % workQueueCount) { case 0: workQ1.EnqueueItem(fidret); break; case 1: workQ2.EnqueueItem(fidret); break; case 2: workQ3.EnqueueItem(fidret); break; case 3: workQ4.EnqueueItem(fidret); break; case 4: workQ5.EnqueueItem(fidret); break; case 5: workQ6.EnqueueItem(fidret); break; case 6: workQ7.EnqueueItem(fidret); break; case 7: workQ8.EnqueueItem(fidret); break; default: workQ1.EnqueueItem(fidret); break; } } } } catch (Exception expall) { Console.WriteLine("Epoll的回调异常: {0}", expall.Message.ToString()); } }
/// <summary>/// 读取数据 /// </summary> private void Redmes(int conn) { var byterecv = new byte[recvSize]; System.IntPtr rbyterecv = Marshal.UnsafeAddrOfPinnedArrayElement <byte>(byterecv, 0); try { bool tepmadd = true; //每次读取500此 for (int j = 0; j < readCount; j++) { var intrecvret = LSocket.recv(conn, rbyterecv, recvSize, 0); if (intrecvret > 0 && intrecvret <= recvSize) { byte[] byt = new byte[intrecvret]; for (int i = 0; i < intrecvret; i++) { byt[i] = Marshal.ReadByte(rbyterecv, i); } #if zhanbao List <byte[]> templistbyte; switch (conn % workQueueCount) { case 0: templistbyte = StickingBag.MakeStickingBag(byt, conn, dicBufferDic1); revMesQue1.EnqueueItem(new resobject() { fid = conn, mes = templistbyte }); break; case 1: templistbyte = StickingBag.MakeStickingBag(byt, conn, dicBufferDic2); revMesQue2.EnqueueItem(new resobject() { fid = conn, mes = templistbyte }); break; case 2: templistbyte = StickingBag.MakeStickingBag(byt, conn, dicBufferDic3); revMesQue3.EnqueueItem(new resobject() { fid = conn, mes = templistbyte }); break; case 3: templistbyte = StickingBag.MakeStickingBag(byt, conn, dicBufferDic4); revMesQue4.EnqueueItem(new resobject() { fid = conn, mes = templistbyte }); break; case 4: templistbyte = StickingBag.MakeStickingBag(byt, conn, dicBufferDic5); revMesQue5.EnqueueItem(new resobject() { fid = conn, mes = templistbyte }); break; case 5: templistbyte = StickingBag.MakeStickingBag(byt, conn, dicBufferDic6); revMesQue6.EnqueueItem(new resobject() { fid = conn, mes = templistbyte }); break; case 6: templistbyte = StickingBag.MakeStickingBag(byt, conn, dicBufferDic7); revMesQue7.EnqueueItem(new resobject() { fid = conn, mes = templistbyte }); break; case 7: templistbyte = StickingBag.MakeStickingBag(byt, conn, dicBufferDic8); revMesQue8.EnqueueItem(new resobject() { fid = conn, mes = templistbyte }); break; default: templistbyte = StickingBag.MakeStickingBag(byt, conn, dicBufferDic1); revMesQue1.EnqueueItem(new resobject() { fid = conn, mes = templistbyte }); break; } #endif #if buzhanbao revMesQue1.EnqueueItem(new resobject() { fid = conn, mes = new List <byte[]>() { byt } }); #endif ////粘包处理 //foreach (var item in templistbyte) //{ // #region 读取消息后做的业务处理 // try // { // RecvCall(conn, item); // } // catch (Exception exrcall) // { // Console.WriteLine("接收消息后调用委托方法异常提示信息:" + exrcall.Message); // } // #endregion //} } else if (intrecvret == 0) { tepmadd = false; SocketClose(conn);//关闭连接 break; } else if (intrecvret == -1) { break; } else { tepmadd = false; SocketClose(conn);//关闭连接 break; } } if (tepmadd) { try { #region 需要再次添加连接的监听 var epollctlretclient = LSocket.epoll_ctl_ADD(epoll_fd, EPOLL_CTL.EPOLL_CTL_ADD, conn, (int)EpollEvents.EPOLLIN); if (epollctlretclient == -1) { Console.WriteLine("epoll_ctl客户端-1: {0}", epollctlretclient.ToString()); } //else //{ // Console.WriteLine("读取消息后把链接添加进去"); //} #endregion } catch (Exception expzz) { Console.WriteLine("添加监听异常:" + expzz.Message); } } } catch (Exception ex2) { Console.WriteLine("接收消息异常提示信息:" + ex2.Message); SocketClose(conn);//关闭连接 } }
private int epoll_fd = -1;//epoolid /// <summary> /// 启动epoll服务 /// </summary> /// <param name="ports">端口</param> /// <param name="ipaddrs">ip</param> /// <param name="recvSizes">每次接收大小</param> /// <param name="RecvCalls">收到消息后的回调用函数</param> /// <param name="SocketCloseCalls">连接断开后的回掉函数</param> /// <param name="listenSizes"> socket监听的队列长度</param> /// <param name="epollSizes"> Epoll监听的最多数量</param> /// <param name="AcceptCalls">有新的连接连入时候的回掉</param> /// <param name="readCounts">处理到某一个连接事件通知后,每次最多读取的次数</param> /// <param name="workQueueCounts">指定接收消息的队列数量,最大是8</param> /// <param name="istickpackage">受否选择粘包</param> /// <returns></returns> public bool Start(ushort ports, string ipaddrs, int recvSizes, RecvCallback RecvCalls, SocketCloseCallback SocketCloseCalls, int listenSizes, int epollSizes, AcceptCallback AcceptCalls, int readCounts, int workQueueCounts) { //开启队列接受粘包数据 revMesQue1.UserWork += UserWorkRrevMesQue; if (revMesQue1.StartUserWork()) { Console.WriteLine("UserWorkRrevMesQue1队列开启成功"); } revMesQue2.UserWork += UserWorkRrevMesQue; if (revMesQue2.StartUserWork()) { Console.WriteLine("UserWorkRrevMesQue2队列开启成功"); } revMesQue3.UserWork += UserWorkRrevMesQue; if (revMesQue3.StartUserWork()) { Console.WriteLine("UserWorkRrevMesQue3队列开启成功"); } revMesQue4.UserWork += UserWorkRrevMesQue; if (revMesQue4.StartUserWork()) { Console.WriteLine("UserWorkRrevMesQue4队列开启成功"); } revMesQue5.UserWork += UserWorkRrevMesQue; if (revMesQue5.StartUserWork()) { Console.WriteLine("UserWorkRrevMesQue5队列开启成功"); } revMesQue6.UserWork += UserWorkRrevMesQue; if (revMesQue6.StartUserWork()) { Console.WriteLine("UserWorkRrevMesQue6队列开启成功"); } revMesQue7.UserWork += UserWorkRrevMesQue; if (revMesQue7.StartUserWork()) { Console.WriteLine("UserWorkRrevMesQue7队列开启成功"); } revMesQue8.UserWork += UserWorkRrevMesQue; if (revMesQue8.StartUserWork()) { Console.WriteLine("UserWorkRrevMesQue8队列开启成功"); } port = ports; ipaddr = ipaddrs; recvSize = recvSizes; RecvCall = RecvCalls; SocketCloseCall = SocketCloseCalls; listenSize = listenSizes; epollSize = epollSizes; AcceptCall = AcceptCalls; readCount = readCounts; workQueueCount = workQueueCounts; //回掉 callback = CSCallbackFunction; var honssin_port = LSocket.htons(port);//端口 Console.WriteLine("端口输出: {0}", honssin_port.ToString()); var htonlip = LSocket.inet_addr(ipaddr); //htonl(0x00000000); Console.WriteLine("IP输出: {0}", htonlip.ToString()); //创建socket sockfd = LSocket.socket(DomainType.AF_INET, SocketTypes.SOCK_STREAM, Protocol.IPPROTO_TCP); Console.WriteLine("创建socket输出: {0}", sockfd.ToString()); //创建参数结构 sockaddr_in addr = new sockaddr_in() { sin_family = DomainType.AF_INET, sin_port = honssin_port, //sin_zero =new byte[] ,// System.Text.Encoding.UTF8.GetBytes(""), sin_addr = new in_addr { s_addr = htonlip } }; //绑定 int bindretrun = LSocket.bind(sockfd, ref addr, 16); Console.WriteLine("绑定输出: {0}", bindretrun.ToString()); if (bindretrun == 0) { Console.WriteLine("bind成功"); } else { return(false); } //监听 int lien = LSocket.listen(sockfd, listenSize); if (lien == 0) { Console.WriteLine("listen成功"); } else { return(false); } epoll_fd = LSocket.epoll_create(epollSize); Console.WriteLine("epoll_create输出: {0}", epoll_fd.ToString()); if (epoll_fd == -1) { return(false); } var epollctlret = LSocket.epoll_ctl_ADD(epoll_fd, EPOLL_CTL.EPOLL_CTL_ADD, sockfd, (int)EpollEvents.EPOLLIN); Console.WriteLine("epoll_ctl注册返回值: {0}", epollctlret.ToString()); if (epollctlret == -1) { return(false); } //开启Epoll Thread th = new Thread(() => { LSocket.PollWait(epoll_fd, epollSize, callback);//开启等待模式 }); th.Start(); //开启线程读取消息-------1个线程池 #region 开启线程读取消息 Thread thr = new Thread(() => { while (true) { var tepm = workQ1.DequeueItem(); if (tepm != null && tepm != 0) { try { Redmes(tepm); } catch (Exception expWork) { Console.WriteLine("读取都列异常: {0}", expWork.Message.ToString()); } } else { Thread.Sleep(20); } } }); thr.Start(); Thread thr2 = new Thread(() => { while (true) { var tepm = workQ2.DequeueItem(); if (tepm != null && tepm != 0) { try { Redmes(tepm); } catch (Exception expWork) { Console.WriteLine("读取都列异常: {0}", expWork.Message.ToString()); } } else { Thread.Sleep(20); } } }); thr2.Start(); Thread thr3 = new Thread(() => { while (true) { var tepm = workQ3.DequeueItem(); if (tepm != null && tepm != 0) { try { Redmes(tepm); } catch (Exception expWork) { Console.WriteLine("读取都列异常: {0}", expWork.Message.ToString()); } } else { Thread.Sleep(20); } } }); thr3.Start(); Thread thr4 = new Thread(() => { while (true) { var tepm = workQ4.DequeueItem(); if (tepm != null && tepm != 0) { try { Redmes(tepm); } catch (Exception expWork) { Console.WriteLine("读取都列异常: {0}", expWork.Message.ToString()); } } else { Thread.Sleep(20); } } }); thr4.Start(); #endregion #region 开启线程读取消息2 Thread thr5 = new Thread(() => { while (true) { var tepm = workQ5.DequeueItem(); if (tepm != null && tepm != 0) { try { Redmes(tepm); } catch (Exception expWork) { Console.WriteLine("读取都列异常: {0}", expWork.Message.ToString()); } } else { Thread.Sleep(20); } } }); thr5.Start(); Thread thr6 = new Thread(() => { while (true) { var tepm = workQ6.DequeueItem(); if (tepm != null && tepm != 0) { try { Redmes(tepm); } catch (Exception expWork) { Console.WriteLine("读取都列异常: {0}", expWork.Message.ToString()); } } else { Thread.Sleep(20); } } }); thr6.Start(); Thread thr7 = new Thread(() => { while (true) { var tepm = workQ7.DequeueItem(); if (tepm != null && tepm != 0) { try { Redmes(tepm); } catch (Exception expWork) { Console.WriteLine("读取都列异常: {0}", expWork.Message.ToString()); } } else { Thread.Sleep(20); } } }); thr7.Start(); Thread thr8 = new Thread(() => { while (true) { var tepm = workQ8.DequeueItem(); if (tepm != null && tepm != 0) { try { Redmes(tepm); } catch (Exception expWork) { Console.WriteLine("读取都列异常: {0}", expWork.Message.ToString()); } } else { Thread.Sleep(20); } } }); thr8.Start(); #endregion return(true); }