是想尝试下心跳包的实现,但是发现完全没起作用,有谁能帮忙看下为什么么?或者能给个可以响应的心跳包例子也行啊
服务端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Runtime.InteropServices;
using System.Collections;
namespace ConsoleApplication1
{
    public class StateObject
    {
        public const int BufferSize = 1024;
        public byte[] buffer = new byte[BufferSize];
        public StringBuilder sb = new StringBuilder();
    }    public class socketstate
    {
        public int connecttime;
        public Socket workSocket = null;
        public StateObject state;
        public bool workstatus=false;
    }
        public class AsynchronousSocketListener
    {
        public static ManualResetEvent allDone = new ManualResetEvent(false);
        public AsynchronousSocketListener()
        {
        }
        static List<socketstate> socketlist = new List<socketstate>();
        public static void StartListening()
        {
            const int acceptcount = 1000;           
            byte[] bytes = new Byte[1024];
            IPAddress ipAddress = IPAddress.Any;
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 6600);
            Socket listener = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);
            try
            {
                listener.Bind(localEndPoint);
                listener.Listen(acceptcount);
                while (true)
                {
                    allDone.Reset();
                    Console.WriteLine("Waiting for a connection...");
                    listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
                    allDone.WaitOne();
                }            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            Console.WriteLine("\nPress ENTER to continue...");
            Console.Read();
        }        const int KEEPALIVESIZE = 12;        static byte[] KeepAlive(int onOff, int keepAliveTime, int keepAliveInterval)
        {
            byte[] buffer = new byte[KEEPALIVESIZE];
            BitConverter.GetBytes(onOff).CopyTo(buffer, 0);
            BitConverter.GetBytes(keepAliveTime).CopyTo(buffer, 4);
            BitConverter.GetBytes(keepAliveInterval).CopyTo(buffer, 8);
            return buffer;
        }        public static void AcceptCallback(IAsyncResult ar)
        {
            allDone.Set();
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);
            handler.IOControl(IOControlCode.KeepAliveValues,KeepAlive(0, 2000, 4000), null);//这里完全没起作用,客户端拔掉网线也没有异常
            socketstate state = new socketstate();
            try
            {
                state.workstatus = true;
                state.workSocket = handler;
                state.state = new StateObject();
                state.workSocket = handler;
                state.connecttime = System.Environment.TickCount;
                state.state = new StateObject();
                socketlist.Add(state);
                handler.BeginReceive(state.state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReadCallback), state);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                state.workstatus = false;
            }
        }        public static void ReadCallback(IAsyncResult ar)
        {                String content = String.Empty;
                socketstate state = (socketstate)ar.AsyncState;
                if ((state == null) || (state.workSocket == null) || (state.workSocket.Connected==false ))
                {
                    Console.WriteLine("null client");
                    state.workstatus = false;
                    return;
                }
                Socket handler = state.workSocket;
                try
                {
                int bytesRead = handler.EndReceive(ar);                if (bytesRead > 0)
                {
                    if (state.state == null)
                    {
                        state.state = new StateObject();
                    }
                    state.state.sb.Append(Encoding.Unicode.GetString(state.state.buffer, 0, bytesRead));
                    content = state.state.sb.ToString();
                    if (content.IndexOf("<EOF>") > -1)
                    {
                        Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
                            content.Length, content);
                        Send(handler, "<ENN>");
                        Send(handler, "<END>");
                    }
                    else
                    {
                        handler.BeginReceive(state.state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReadCallback), state);
                        Console.WriteLine(content+" is receive");
                    }
                }
                else//当读取到的值<=0时就表示客户端断开了
                {
                    state.workstatus = false;
                    Console.WriteLine("socket is disconnect");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                state.workstatus = false;
            }
        }        private static void Send(Socket handler, String data)
        {
            try
            {
                byte[] byteData = Encoding.Unicode.GetBytes(data);
                handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket handler = (Socket)ar.AsyncState;
                if ((handler == null)||(handler.Connected==false))
                {
                    return;
                }
                int bytesSent = handler.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to client.", bytesSent);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        public static int Main(String[] args)
        {
            StartListening();
            return 0;
        }
    }
}

解决方案 »

  1.   

    客户端先不贴了,问题应该在服务端的,我只设了单向心跳包,但是客户端拔掉网线却完全没有响应,同步模式的tcpsocket我也试过了,相同的情况,有谁能帮帮忙么?
      

  2.   

    话说我也知道心跳包是在udp用的,tcp可以通过timeout来判断超时,不过只是想学下心跳的使用,所以做个例子试下,完全没人理啊~囧
      

  3.   

    你上面的这段代码是在网上看到的吧。我以前也看到过,但是我也没做出效果来。不知道为什么。最后改了方式,KeepAlive是socket自带的消息机制吧,它默认是很久自动检测对方是否还在,至于多久,我忘记了。网上的办法是,改这个时间为1秒或者多少。来实现类似心跳包。
    其实心跳包很好理解,个人理解为:
    每一定时间给对方发生个消息,如果对方还在,那么就回你一个消息(其实我觉得没必要回,因为有个connected属性,它是获取上一次连接,发生状态的,虽然是获取上一次,但是你发送后马上获取就类似当前状态了,这种方法用在非阻塞下可以。如果是阻塞式的socket你会发现你如果你又recieve线程,这个地方会报异常,因为receive正在阻塞时,突然断开了。所以阻塞的可以通过try catch)。最后我用伪代码示意哈。你自己操作就OK了
    1.连接socket(废话)
    2.单起一个线程来当心跳,每1秒钟向服务器发送HEART
    这个就是心跳啦网上的那个方法你没必要此时去研究,原因很简单,因为你不懂,代码也是抄袭的,下次又忘记了,又Copy一次,有意思么?程序员还是自己写代码。当能力够了自然就懂了
      

  4.   

    其实你说的我已经实现了tcp socket用超时判断和发送小包两种方式来判断客户端断开,只不过我想试验下心跳包的具体机制,既然微软提供了,我就想详细学习下呗
      

  5.   

    另外这个代码是按照微软提供的demo自己修改的,不是copy啊