Tcp客户端无法在WIN8上断开连接,但在WIN7上完全断开连接

时间:2013-03-25 15:14:28

标签: c# tcplistener

我使用此代码与tcp客户端进行通信。在WIN7上一切运行良好,但在WIN8上,tcp客户端无法与服务器断开连接。我使用Hercules软件测试功能。所有tcp客户端都在线上与服务器断开连接

DisconnectDevice(idx, devType, ip, port);

但是在WIN8上,软件不会落在这一行上。等待你的想法!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using Microsoft.Win32;

namespace OperationService.Comm
{
public sealed class Communication
{
    #region variables

    private static readonly Communication _instance = new Communication();

    #region low level communication

    private class _message
    {
        public const byte PACKET_START_CHAR = 0x23;
        public const int DATA_LENGTH_BYTE_NUM = 2;
        public const int EPOCH_BYTE_NUM = 4;
        public const byte PACKET_END_CHAR = 0x24;

        public enum State : int
        {
            Start,
            DataLength,
            Epoch,
            CmdType,
            Data,
            ChkSum,
            End
        }

        public byte Start { get; set; }
        public UInt16 DataLength { get; set; }
        public UInt32 Epoch { get; set; }
        public byte CmdType { get; set; }
        public byte[] Data { get; set; }
        public byte ChkSum { get; set; }
        public byte End { get; set; }

        public int DataLenCtr { get; set; }
        public int EpochCtr { get; set; }
        public int DataCtr { get; set; }
        public int CurrentChkSum { get; set; }

        public State MsgState { get; set; }

        public _message()
        {
            this.MsgState = State.Start;
            this.DataLenCtr = 0;
            this.EpochCtr = 0;
            this.DataCtr = 0;
            this.CurrentChkSum = 0;
        }
    }

    #endregion

    #region threading

    private const int MAX_TCP_BUFFER_LENGTH = 8192;
    private const int CLIENT_COMM_TASK_SLEEP_VALUE = 1000;
    private static bool _threadStartFlag;
    private static Thread _pmcListeningThread;
    private static Thread _pmdListeningThread;
    private static Thread _guiListeningThread;
    private static Thread _mobileListeningThread;
    private const int PMC_LISTENING_PORT = 1234;
    private const int PMD_LISTENING_PORT = 1233;
    private const int GUI_LISTENING_PORT = 1232;
    private const int MOBILE_LISTENING_PORT = 1231;
    private static string _localIp;
    private static string _mobileEntryIp;

    #endregion

    #endregion

    #region ctor

    private Communication()
    {
        _threadStartFlag = false;
        _localIp = Program.GetLocalIp();
        _mobileEntryIp = _localIp;
    }

    #endregion

    #region methods

    public static bool Initialize()
    {
        bool RetSt = false;

        try
        {
            if (!RunTasks())
                return false;

            RetSt = true;
        }
        catch (Exception ex)
        {
            Program.WriteEventLog(ex, EventLogEntryType.Error);
        }

        return RetSt;
    }

    public static bool Send(TcpClient tcpClient, List<byte> data)
    {
        Program.DebugWrite(tcpClient.ToString());
        for (int i = 0; i < data.Count; i++)
            Program.DebugWrite(data[i].ToString());
        return true;
    }

    private static bool RunTasks()
    {
        bool RetSt = false;

        try
        {
            if (!_threadStartFlag)
            {
                _pmcListeningThread = new Thread(() => ListeningTask(PMC_LISTENING_PORT));
                _pmcListeningThread.IsBackground = true;
                _pmcListeningThread.Start();

                _pmdListeningThread = new Thread(() => ListeningTask(PMD_LISTENING_PORT));
                _pmdListeningThread.IsBackground = true;
                _pmdListeningThread.Start();

                _guiListeningThread = new Thread(() => ListeningTask(GUI_LISTENING_PORT));
                _guiListeningThread.IsBackground = true;
                _guiListeningThread.Start();

                _mobileListeningThread = new Thread(() => ListeningTask(MOBILE_LISTENING_PORT));
                _mobileListeningThread.IsBackground = true;
                _mobileListeningThread.Start();

                _threadStartFlag = true;
            }

            RetSt = true;
        }
        catch (Exception ex)
        {
            Program.WriteEventLog(ex, EventLogEntryType.Error);
        }

        return RetSt;
    }

    private static void ListeningTask(int ListeningPort)
    {
        TcpListener tcpListener;

        try
        {
            tcpListener = new TcpListener(IPAddress.Any, ListeningPort);
            tcpListener.Start();
        }
        catch (Exception ex)
        {
            Program.WriteEventLog(ex, EventLogEntryType.Error);
            return;
        }

        Program.DebugWrite(string.Format("Tcp listener is active on Port:{0}.", ListeningPort));

        while (true)
        {
            try
            {
                TcpClient newTcpClient = tcpListener.AcceptTcpClient();
                string ip = ((IPEndPoint)newTcpClient.Client.RemoteEndPoint).Address.ToString();
                string port = ((IPEndPoint)newTcpClient.Client.RemoteEndPoint).Port.ToString();

                int idx = -1;
                DeviceType devType;
                bool isOnline = false;
                bool isAllowed = false;

                if (ListeningPort == PMC_LISTENING_PORT)
                {
                    devType = DeviceType.Controller;

                    idx = Program.Topology.Controllers.FindIndex(c => c.Ip == ip);
                    if (idx >= 0)
                    {
                        if (!object.ReferenceEquals(Program.Topology.Controllers[idx], null))
                        {
                            isAllowed = true;
                            if (Program.Topology.Controllers[idx].Runtime.IsOnline)
                                isOnline = true;
                        }
                    }
                }
                else if (ListeningPort == PMD_LISTENING_PORT)
                {
                    devType = DeviceType.Display;

                    idx = Program.Topology.Displays.FindIndex(d => d.Ip == ip);
                    if (idx >= 0)
                    {
                        if (!object.ReferenceEquals(Program.Topology.Displays[idx], null))
                        {
                            isAllowed = true;
                            if (Program.Topology.Displays[idx].Runtime.IsOnline)
                                isOnline = true;
                        }
                    }
                }
                else if (ListeningPort == GUI_LISTENING_PORT)
                {
                    devType = DeviceType.Gui;

                    if (ip == _localIp)
                    {
                        isAllowed = true;
                        if (Program.Topology.Gui.IsOnline)
                            isOnline = true;
                    }

                }
                else if (ListeningPort == MOBILE_LISTENING_PORT)
                {
                    devType = DeviceType.Mobile;

                    if (ip == _mobileEntryIp)
                    {
                        isAllowed = true;
                        isOnline = false;
                    }
                }
                else
                    return;

                if (isAllowed)
                {
                    if (!isOnline)
                    {
                        CreateTcpClient(idx, devType, newTcpClient);
                        ConnectDevice(idx, devType, ip, port);

                        Thread ClientCommThread = new Thread(() => ClientCommTask(idx, devType, newTcpClient, ip, port));
                        ClientCommThread.IsBackground = true;
                        ClientCommThread.Start();
                    }
                    else
                    {
                        Program.WriteEventLog(string.Format("Tcp client from IP:{0} and Port:{1} is already online.", ip, port), EventLogEntryType.Warning);
                        newTcpClient.Close();
                    }
                }
                else
                {
                    Program.WriteEventLog(string.Format("Unauthorized connection attempt from IP:{0} and Port:{1}.", ip, port), EventLogEntryType.Warning);
                    newTcpClient.Close();
                }
            }
            catch (SocketException ex)
            {
                Program.WriteEventLog(ex, EventLogEntryType.Error);
            }
            catch (Exception ex)
            {
                Program.WriteEventLog(ex, EventLogEntryType.Error);
            }
        }
    }

    private static void ClientCommTask(int idx, DeviceType devType, TcpClient tcpClient, string ip, string port)
    {
        NetworkStream ClientDataStream = tcpClient.GetStream();
        _message msg = new _message();

        byte[] Data = new byte[MAX_TCP_BUFFER_LENGTH];
        int DataLen;

        while (true)
        {
            try
            {
                try
                {
                    DataLen = ClientDataStream.Read(Data, 0, Data.Length);
                }
                catch
                {
                    // network stream data is not avaliable in urgent case use
                    DataLen = 0;
                }

                if (DataLen == 0)
                {
                    // the client has disconnected from the server
                    DisconnectDevice(idx, devType, ip, port);
                    break;
                }
                else
                {

                }

                Thread.Sleep(CLIENT_COMM_TASK_SLEEP_VALUE);
            }
            catch (Exception ex)
            {
                Program.WriteEventLog(ex, EventLogEntryType.Error);
            }
        }

        DisposeTcpClient(idx, devType, tcpClient);
    }

    private static void ParseMsg(_message msg)
    {
        try
        {
            switch (msg.CmdType)
            { 
                case 0x00:
                    if (Program.Topology.Gui.IsOnline)
                        Console.WriteLine("gui on");
                    else
                        Console.WriteLine("gui off");
                    break;
            }
        }
        catch (Exception ex)
        {
            Program.WriteEventLog(ex, EventLogEntryType.Error);
        }
    }

    private static void ConnectDevice(int idx, DeviceType devType, string ip, string port)
    {
        try
        {
            if (devType == DeviceType.Controller)
            {
                Program.WriteEventLog(string.Format("Controller device from IP:{0} and Port:{1} connected.", ip, port), EventLogEntryType.Information);
                Program.Topology.Controllers[idx].Runtime.IsOnline = true;
                Program.Topology.Controllers[idx].Runtime.Port = int.Parse(port);
                Program.Topology.Controllers[idx].Runtime.Ip = ip;
            }
            else if (devType == DeviceType.Display)
            {
                Program.WriteEventLog(string.Format("Display device from IP:{0} and Port:{1} connected.", ip, port), EventLogEntryType.Information);
                Program.Topology.Displays[idx].Runtime.IsOnline = true;
                Program.Topology.Displays[idx].Runtime.Port = int.Parse(port);
                Program.Topology.Displays[idx].Runtime.Ip = ip;
            }
            else if (devType == DeviceType.Gui)
            {
                Program.WriteEventLog(string.Format("Gui device from IP:{0} and Port:{1} connected.", ip, port), EventLogEntryType.Information);
                Program.Topology.Gui.IsOnline = true;
                Program.Topology.Gui.Port = int.Parse(port);
                Program.Topology.Gui.Ip = ip;
            }
            else if (devType == DeviceType.Mobile)
            {
                Program.WriteEventLog(string.Format("Mobile device from IP:{0} and Port:{1} connected.", ip, port), EventLogEntryType.Information);
            }
        }
        catch (Exception ex)
        {
            Program.WriteEventLog(ex, EventLogEntryType.Error);
        }
    }

    private static void DisconnectDevice(int idx, DeviceType devType, string ip, string port)
    { 
        try
        {
            if (devType == DeviceType.Controller)
            {
                Program.WriteEventLog(string.Format("Controller device from IP:{0} and Port:{1} disconnected.", ip, port), EventLogEntryType.Warning);
                Program.Topology.Controllers[idx].Runtime.IsOnline = false;
                Program.Topology.Controllers[idx].Runtime.Port = -1;
                Program.Topology.Controllers[idx].Runtime.Ip = string.Empty;
            }
            else if (devType == DeviceType.Display)
            {
                Program.WriteEventLog(string.Format("Display device from IP:{0} and Port:{1} disconnected.", ip, port), EventLogEntryType.Warning);
                Program.Topology.Displays[idx].Runtime.IsOnline = false;
                Program.Topology.Displays[idx].Runtime.Port = -1;
                Program.Topology.Displays[idx].Runtime.Ip = string.Empty;
            }
            else if (devType == DeviceType.Gui)
            {
                Program.WriteEventLog(string.Format("Gui device from IP:{0} and Port:{1} disconnected.", ip, port), EventLogEntryType.Warning);
                Program.Topology.Gui.IsOnline = false;
                Program.Topology.Gui.Port = -1;
                Program.Topology.Gui.Ip = string.Empty;
            }
            else if (devType == DeviceType.Mobile)
            {
                Program.WriteEventLog(string.Format("Mobile device from IP:{0} and Port:{1} disconnected.", ip, port), EventLogEntryType.Warning);
            }
        }
        catch (Exception ex)
        {
            Program.WriteEventLog(ex, EventLogEntryType.Error);
        }
    }

    private static void CreateTcpClient(int idx, DeviceType devType, TcpClient client)
    {
        try
        {
            if (devType == DeviceType.Controller)
            {
                Program.Topology.Controllers[idx].Runtime.TcpClient = client;
            }
            else if (devType == DeviceType.Display)
            {
                Program.Topology.Displays[idx].Runtime.TcpClient = client;
            }
            else if (devType == DeviceType.Gui)
            {
                Program.Topology.Gui.TcpClient = client;
            }
            else if (devType == DeviceType.Mobile)
            {
            }
        }
        catch (Exception ex)
        {
            Program.WriteEventLog(ex, EventLogEntryType.Error);
        }
    }

    private static void DisposeTcpClient(int idx, DeviceType devType, TcpClient client)
    {
        try
        {
            if (devType == DeviceType.Controller)
            {
                Program.Topology.Controllers[idx].Runtime.TcpClient.Client.Close();
                Program.Topology.Controllers[idx].Runtime.TcpClient = null;
            }
            else if (devType == DeviceType.Display)
            {
                Program.Topology.Displays[idx].Runtime.TcpClient.Client.Close();
                Program.Topology.Displays[idx].Runtime.TcpClient = null;
            }
            else if (devType == DeviceType.Gui)
            {
                Program.Topology.Gui.TcpClient.Client.Close();
                Program.Topology.Gui.TcpClient = null;
            }
            else if (devType == DeviceType.Mobile)
            {
                client.Client.Close();
                client = null;
            }
        }
        catch (Exception ex)
        {
            Program.WriteEventLog(ex, EventLogEntryType.Error);
        }
    }

    #endregion
}

}

1 个答案:

答案 0 :(得分:0)

我在下面找到了链接。当我尝试从另一台计算机而不是localhost时,它工作正常!

TCP connection problems in Windows 8

Can't use StreamSocket to connect to a TcpListener

http://msdn.microsoft.com/en-us/library/windows/apps/Hh780593.aspx