三丶TCP处理客户端异常与正常关闭情况

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_33951440/article/details/79863661

这个问题在TX 面试的时候问过我。 不过当时demo并没有注意这个问题, 还好面试官换问题了。。


一: 正常关闭:

    如果客户端是主动申请close , 会发送一串byte数 为0的数据到服务器,服务器就会收到count个数为0,则表示正常关闭。此时服务器正常操作close

(这里有个问题是,即便客户端自己正常发送空数据进来,服务器也不会收到0数据,所以当服务器收到0的时候就代表客户端请求正常关闭)。

二:异常关闭:

    如果客户端强制点了X ,则代表未经过(退出游戏)正常关闭操作,当服务器捕获异常(远程主机强制关闭),则停止这个socket连接

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;

namespace TcpServer
{
    class Program
    {
        static byte[] dataBuffer = new byte[1024];
        static void Main(string[] args)
        {
            StartServerAsync();
            Console.ReadKey();
        }
        static void StartServerAsync()
        {
            Socket socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress iPAddress = IPAddress.Parse("192.168.200.1");
            IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, 88);
            socketServer.Bind(iPEndPoint);

            socketServer.Listen(10);
            //Socket clientSocket = socketServer.Accept(); 下面支持多个客户端,改为异步, 之前c++服务器用的epoll这里似乎不需要关注
            socketServer.BeginAccept(AcceptCallBack, socketServer); 
        }

        static void AcceptCallBack(IAsyncResult ar)
        {
            Socket socketServer = ar.AsyncState as Socket;
            Socket socketClient = socketServer.EndAccept(ar);

            string msg = "Hello";

            socketClient.Send(System.Text.Encoding.UTF8.GetBytes(msg)); 

            socketClient.BeginReceive(dataBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, socketClient);
            socketServer.BeginAccept(AcceptCallBack, socketServer);
        }

        static void ReceiveCallBack(IAsyncResult ar)
        {
            //            ar.AsyncState 可以获得之前传递的object
            Socket socketClient=null ;
            try
            {
                socketClient = ar.AsyncState as Socket;
                int count = socketClient.EndReceive(ar);
                if (count == 0)
                {
                    //即便是空数据也不会是0,客户端不会发送空数据,  只有在结束时才有0的可能性
                    socketClient.Close();
                    return;
                }
                string msgReceive = Encoding.UTF8.GetString(dataBuffer, 0, count);
                Console.WriteLine(msgReceive);
                socketClient.BeginReceive(dataBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, socketClient);
            } 
            catch (Exception e)
            {   
                Console.WriteLine(e);
                if (socketClient != null)
                {
                    socketClient.Close();
                }
            }    
        }

        void StartServerSync()
        {

            Socket socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPAddress iPAddress = IPAddress.Parse("192.168.200.1");
            IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, 88);
            socketServer.Bind(iPEndPoint);

            socketServer.Listen(10);
            Socket clientSocket = socketServer.Accept();
            string msg = "Hello";
            clientSocket.Send(System.Text.Encoding.UTF8.GetBytes(msg));
            byte[] databuffer = new byte[1024];
            int count = clientSocket.Receive(databuffer);
            string megReceive = System.Text.Encoding.UTF8.GetString(databuffer, 0, count);
            Console.Write(databuffer);
            clientSocket.Close();
            socketServer.Close();

        }
    }
}

展开阅读全文

TCP长连接 客户端关闭时怎么会有异常??急死俺了

10-21

服务端: rn Private Sub FrmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Loadrn listener1 = New TcpListener(System.Net.IPAddress.Parse("192.168.4.171"), "30000")rn listener1.Start()rn listening1 = Truern Timer4.Enabled = Truern end subrn rn Private Sub Timer4_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer4.Tickrn Dim CurThreadStart As ThreadStartrnrn Timer4.Enabled = Falsern If listener1.Pending() Thenrn CurThreadStart = New ThreadStart(AddressOf request)rn CurThread1 = New Thread(CurThreadStart)rn CurThread1.Start()rn End Ifrn Timer4.Enabled = Truern End Subrnrn Public Sub request()rn CurThread1 = System.Threading.Thread.CurrentThread()rnrn Dim buf(3000) As Bytern Dim senddata As Stringrn Dim intLen As Integerrn Dim ReceivedData As Stringrn Dim cursocket As Socketrn cursocket = listener1.AcceptSocketrn cursocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000)rn cursocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000)rn Tryrn While listening1rn Thread.Sleep(100)rn If cursocket.Available > 0 Thenrnrnrn '接收来自绑定的Socket的数据rn intLen = cursocket.Receive(buf, cursocket.Available, 0)rn '将接收到的数据转化成相应编码的字符串rn ReceivedData = System.Text.Encoding.Default.GetString(buf, 0, intLen)rn System.Console.WriteLine(ReceivedData)rn If ReceivedData = "close" Thenrn System.Threading.Thread.Sleep(1000)rnrn System.Console.WriteLine(ReceivedData)rn cursocket.Shutdown(Net.Sockets.SocketShutdown.Both)rn cursocket.Close()rn Exit Whilern End Ifrn End Ifrn If bln_rfid = True Thenrn bln_rfid = Falsern senddata = "张三:李四:王五" rn buf = System.Text.Encoding.Default.GetBytes(senddata)rn cursocket.Send(buf, buf.Length, 0)rn End Ifrn rn End Whilernrn Catch ex As Exceptionrn cursocket.Shutdown(Net.Sockets.SocketShutdown.Both)rn cursocket.Close()rn System.Console.WriteLine(ex.Message + ex.Source + "关掉了")rn End Tryrnrn End Subrnrnrn客户端:rn Private Sub getconnect()rn Dim ip As System.Net.IPAddressrn Dim strrecvdatabegin As Stringrn Dim buf(255) As Bytern Dim ilen As Integerrn Dim beginbuff(255) As Bytern Dim strtemp As Stringrn Dim strtemp2 As Stringrn Dim strtemp3 As Stringrn Dim strtemp4 As Stringrnrn Tryrn tcpclient_info = New System.Net.Sockets.TcpClientrnrn ip = System.Net.IPAddress.Parse(str_ip)rn tcpclient_info.Connect(ip, "30000")rn tcpclient_info.LingerState.Enabled = Falsern While (True)rn System.Threading.Thread.Sleep(100)rn ReDim beginbuff(255)rn ReDim buf(255)rn Application.DoEvents()rn lnlasttime = Environment.TickCountrnrn While Not tcpclient_info.GetStream.DataAvailable()rn Application.DoEvents()rn End Whilernrn 'If Environment.TickCount - lnlasttime < 1000 And bln_close = False Thenrn If tcpclient_info.GetStream.DataAvailable() Thenrn tcpclient_info.GetStream.Read(beginbuff, 0, beginbuff.length)rn strrecvdatabegin = System.Text.Encoding.Default.GetString(beginbuff, 0, beginbuff.length)rn txtTemp.Text = strrecvdatabeginrn End Ifrn End Whilernrn [color=#FF0000]Catch ex As Exception[/color] rn 'System.Console.Write(ex.Message)rn End Tryrnrn End Subrnrn Private Sub frm_manager_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closingrn Dim strdata As Stringrn Dim buf(255) As Byternrn strdata = "close"rn buf = System.Text.Encoding.Default.GetBytes(strdata)rn tcpclient_info.GetStream.Write(buf, 0, buf.Length)rn tcpclient_info.GetStream.Flush()rn blnreturn = Falsern Timer1.Enabled = Falsern Timer2.Enabled = Falsern tcpclient_info.Close()rn Me.Close()rn Application.Exit()rnrn End Subrnrn我建的是长连接,连上之后不断开,服务端一有数据就往客户端发送.rn在客户端关闭的时候给服务器发送一个close的字段,显示客户端关闭连接了,然后服务端把这个线程断掉.但是客户端这边会报异常,报在红颜色字的那里,怎么都找不出来原因,不过我断点跟踪过好象是它一直会在While Not tcpclient_info.GetStream.DataAvailable()这个循环里面跳不出来,到底怎么解决啊,困扰死了 论坛

没有更多推荐了,返回首页