首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

Win7上Socket服务端通信错误退出

2013-01-11 
Win7下Socket服务端通信异常退出本帖最后由 zpj888 于 2012-12-29 15:22:36 编辑socket通信时,服务端会造

Win7下Socket服务端通信异常退出
本帖最后由 zpj888 于 2012-12-29 15:22:36 编辑 socket通信时,服务端会造成程序死掉,而且是无法捕捉到的异常退出
经过数天多次测试,XP下正常,绝大部分的WIN7系统会退。
以下是写的专门用于测试该问题的小程序,一个服务端,一个客户端。
其中服务端开始后,客户端指定本机的IP地址即可,注意不要使用回环地址,测试时发现回环地址不容易退。
客户端连接200个socket,每个socket频繁收发数据,很快程序退出
开发环境:VS2010,C#,Dot Net4.0
完整程序及代码链接:http://l5.yunpan.cn/lk/QkBwwZxj6wDzT
(代码没有处理各种连接及断开的异常情况,不影响测试)

请各位帮忙看看问题所在,是不是WIN7的什么补丁要装一下?测试WIN7机装了SP1,拿360打了所有补丁,一样会退

服务端监听代码:


public class 监听线程
{
    public static int ClientCount = 0;
    private static List<服务端通信线程> list = new List<服务端通信线程>();
    private static string Ip = "";
    private static int Port = 0;

    public static void 启动监听线程(string strIp, int port)
    {
        Ip = strIp;
        Port = port;
        var th = new Thread(Run);
        th.IsBackground = true;
        th.Start();
    }

    private static void Run()
    {
        var tcpListener = new TcpListener(IPAddress.Parse(Ip), Port);
        tcpListener.Start();
        while (true)
        {
            Thread.Sleep(100);
            var tcpClient = tcpListener.AcceptTcpClient();

            var obj = new 服务端通信线程();
            obj.启动通信线程(tcpClient);
            list.Add(obj);
            ClientCount++;
        }
    }
}


服务端通信核心代码:

public class 服务端通信线程
{
    private TcpClient tcpClient = null;

    public void 启动通信线程(TcpClient tcpClient)
    {
        this.tcpClient = tcpClient;
        this.tcpClient.ReceiveTimeout = 2000;
        this.tcpClient.SendTimeout = 2000;

        var th = new Thread(Run);
        th.IsBackground = true;
        th.Start();
    }

    private int ReadByte(byte[] buffer, int offset, int size)
    {
        try
        {

            return tcpClient.GetStream().Read(buffer, offset, size);


        }
        catch
        {
            tcpClient.Close();
            return 0;
        }
    }

    private bool WriteByte(byte[] buffer, int offset, int size)
    {
        try
        {
            tcpClient.GetStream().Write(buffer, offset, size);
            return true;
        }
        catch
        {
            tcpClient.Close();
            return false;
        }
    }
        
    private bool 接收定长数据(byte[] buff, int offset, int needLen)
    {
        int recvLen = 0;
        while (true)
        {
            int len = ReadByte(buff, offset + recvLen, needLen - recvLen);
            if (len <= 0) return false;
            recvLen += len;
            if (recvLen == needLen) return true;
        }
    }

    private void Run()
    {
        const int sendLen = 100;
        const int readLen = 10;
        var readBuff = new byte[readLen + 4];
        var sendBuff = new byte[sendLen + 4];
        var array = BitConverter.GetBytes(sendLen);
        for (int i = 0; i < 4; i++) sendBuff[i] = array[i];
        while (tcpClient.Connected)
        {
            Thread.Sleep(0);
            if (!接收定长数据(readBuff, 0, 4) ||  // 接收4个字节报文头
                BitConverter.ToInt32(readBuff, 0) != readLen || // 报文头有误
                !接收定长数据(readBuff, 4, readLen))  // 接收报文内容
            {


                tcpClient.Close();
                continue;
            }

            WriteByte(sendBuff, 0, sendBuff.Length);
        }

        监听线程.ClientCount--;
    }
}



客户端管理代码

    partial class 客户端通信线程
    {
        private static List<客户端通信线程> list = new List<客户端通信线程>();
        private static string Ip = "";
        private static int Port = 0;
        public static void 启动客户端线程(string strIp, int port, int maxCount)
        {
            Ip = strIp;
            Port = port;
            for (int i = 0; i < maxCount; i++)
            {
                var obj = new 客户端通信线程();
                obj.启动通信线程();
                list.Add(obj);
            }
        }

        public static int 获取正常连接数()
        {
            int count = 0;
            foreach (var item in list)
            {
                if (item.Active) count++;
            }
            return count;
        }
    }



客户端通信代码

    public partial class 客户端通信线程
    {
        private TcpClient tcpClient = new TcpClient();
        public bool Active = false;

        public void 启动通信线程()
        {
            this.tcpClient.ReceiveTimeout = 2000;
            this.tcpClient.SendTimeout = 2000;

            var th = new Thread(Run);


            th.IsBackground = true;
            th.Start();
        }

        private bool Connect()
        {
            try
            {
                tcpClient = new TcpClient();
                tcpClient.Connect(Ip, Port);
                return tcpClient.Connected;
            }
            catch
            {
                return false;
            }
        }

        // 下面的3个方法与服务端完全一致,不重复贴出
        private int ReadByte(byte[] buffer, int offset, int size)
        private bool WriteByte(byte[] buffer, int offset, int size)
        private bool 接收定长数据(byte[] buff, int offset, int needLen)

        private void Run()
        {
            const int sendLen = 10;
            const int readLen = 100;
            var readBuff = new byte[readLen + 4];
            var sendBuff = new byte[sendLen + 4];
            var array = BitConverter.GetBytes(sendLen);
            for (int i = 0; i < 4; i++) sendBuff[i] = array[i];
            while (true)
            {
                Thread.Sleep(50);

                this.Active = tcpClient.Connected;//用于界面显示连接数
                if (!tcpClient.Connected && !Connect())
                {
                    Thread.Sleep(500);
                    continue;
                }



                for (int i = 0; i < 20; i++)
                {// 连续通信多次
                    if (!tcpClient.Connected) break;
                    WriteByte(sendBuff, 0, sendBuff.Length);

                    if (!接收定长数据(readBuff, 0, 4) ||  // 接收4个字节报文头
                        BitConverter.ToInt32(readBuff, 0) != readLen || // 报文头有误
                        !接收定长数据(readBuff, 4, readLen))  // 接收报文内容
                    {
                        tcpClient.Close();
                        continue;
                    }
                }
            }
        }
    }

socket .net winform c#
[解决办法]
主线程外的线程出现错误自然直接退了
撸过 我一般加try catch
[解决办法]
楼主运行cmd,再从cmd里运行你的程序
程序出错了,上面会显示错误信息的
[解决办法]
引用:
try catch只是屏蔽问题,我这里特意让它报错的,始终没找到WIN7下报错的原因

try catch 除了屏蔽问题。还可以查找问题。把异常写入日志。好查问题。
既然已经用了socket干嘛还要用tcplister,tcpclient??
[解决办法]
mark 一下 ,我也碰到过 捕捉不到任何错误 ,但是又异常退出的情况

热点排行