大家好,我用TcpListener类创建了一个对象进行本机10000端口监听,但考虑安全性,肯定不希望外界任何人都可以连接。可能有人会说,别人不知道端口号?当我感觉端口可以扫描的吧(网上经常看到说扫描端口的,膜拜中)。
那怎么办呢?我看QQ登陆都需要用户名和密码,那么是不是这样一个原理。我客户端先CONNECT远端服务器,然后把用户名和密码发过去,服务器端验证是否正确,然后才运行通信呢?

解决方案 »

  1.   

    消息的验证使用:发送用户名+密码,服务器比对的方式可以吗?
    过滤?这个概念不是很清楚,怎么过滤?SOCKET类中有提供方法进行过滤操作的吗?
      

  2.   

    可以我现在不明白怎么进行过滤操作哟?有人说要写底层防火墙进行控制,这好像很难啊!
    也有人说通过我上面说的方法,但SOCKET类中具体哪个方法或多个方法可以实现呢?我仔细看了MSDN,但好像没找到,能说的具体点吗?
      

  3.   

    就是服务端accept之后在特定时间内检查该连接是否有内容可读,如果没有,就关闭,如果有,第一个包的内容不符合(按照你的方式就是该用户名和密码不存在),也关闭。
    没有底层的方法可以自动实现这个,而且就是按照这些方法去做了,也不能阻止对方不停的connect。
      

  4.   

    这个没有办法吧,在发消息时,必须是已经建立连接才可以。如果你真想这么做,你可以把这个事情交给防火墙来做这事,比较合适,如果你要根据信息来判断允不允许连接,那么就必须经过三次握手(连接已经建立)你可以百度一下,DDOS
      

  5.   

    如果直接关闭,使用CLOSE方法吗?但是这样是不是也会导致合法用户不能正常连接呢?
      

  6.   

    我现在想法是建立连接后,进行一个校验,合法用户就继续,不合法的就想法切断连接(当然这里切断连接的办法还没想到)!
    另外通过防火墙方案,我有点疑问?因为客户端IP是未知的,防火墙只能针对某IP进行阻止吧!是否行不通?防火墙可以检测出恶意连接,然后禁止连接吗?
      

  7.   

    直接close掉该socket就行了,tcp下,每个客户端都应该在服务段有一个相应的socket,关闭某个客户端的不会影响其他客户端。
      

  8.   


    DDOS攻击或者是其它的攻击 对于防御方来说总是被动的`不管你用什么方式来防着都不太管用
    就像熊猫烧香一样`谁知道明天会出什么样的病毒或者攻击方式  再者说微软的"零日漏洞" 都没有办法
    提前预料到`建议 在建立连接请求的时候加上一个暗号之类的东西` 客户端发一个标识性的东西,服务器接到以后解析`
    合法的才接入`如果暗号不对就算你IP跟端口号一样也不让你连`直接给你喀嚓掉~ 不知道这样行不行~
    现在我在干这样的事都是这样做`
      

  9.   

    服务端和客户端任意一端调用了close,这个连接都会关闭。
      

  10.   

    TO:lizhibin11服务端和客户端任意一端调用了close,这个连接都会关闭。我在服务器调用了CLOSE方法关闭了,可是这样是不是也会导致其它和服务器已经连接的客户端也断开呢!因为服务器往往都是开一个端口供多个客户端连接的撒!
      

  11.   

    不会的,关闭socket和关闭端口不是一码事,每个客户端在连接到你的服务端后,都有独自的socket。
      

  12.   

    http://topic.csdn.net/u/20110317/08/aeaa24fe-f95e-4691-aba1-ba875333851a.html
      

  13.   

    我自己写了个测试例子,可CLOSE掉SOCKET后,好像原本跟服务器合法连接也断开了。请帮忙看看!
    服务器端:
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;namespace ConsoleApplication2
    {
        // State object for reading client data asynchronously
        public class StateObject
        {
            // Client  socket.
            public Socket workSocket = null;
            // Size of receive buffer.
            public const int BufferSize = 1024;
            // Receive buffer.
            public byte[] buffer = new byte[BufferSize];
            // Received data string.
            public StringBuilder sb = new StringBuilder();
        }    public class AsynchronousSocketListener
        {
            // Thread signal.
            //通知一个或多个正在等待的线程已发生事件ManualResetEvent
            public static ManualResetEvent allDone = new ManualResetEvent(false);        public AsynchronousSocketListener()
            {
            }        public static void StartListening()
            {
                // Data buffer for incoming data.
                byte[] bytes = new Byte[1024];            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"),20000);            // Create a TCP/IP socket.
                Socket listener = new Socket(AddressFamily.InterNetwork,
                    SocketType.Stream, ProtocolType.Tcp);            try
                {
                    listener.Bind(localEndPoint);
                    listener.Listen(2);                while (true)
                    {
                        // Set the event to nonsignaled state.
                        allDone.Reset();   //将事件状态设置为非终止状态,导致线程阻止。                    // Start an asynchronous socket to listen for connections.
                        Console.WriteLine("Waiting for a connection...");
                        listener.BeginAccept(
                            new AsyncCallback(AcceptCallback),
                            listener);                    // Wait until a connection is made before continuing.
                        allDone.WaitOne();//阻止当前线程,直到当前 WaitHandle 收到信号。 
                    }            }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }            Console.WriteLine("\nPress ENTER to continue...");
                Console.Read();        }        public static void AcceptCallback(IAsyncResult ar)
            {   allDone.Set();//将事件状态设置为终止状态,允许一个或多个等待线程继续。            Socket listener = (Socket)ar.AsyncState; 
                  Socket handler = listener.EndAccept(ar);            // Create the state object.
                StateObject state = new StateObject();
                state.workSocket = handler;
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReadCallback), state);
            }        public static void ReadCallback(IAsyncResult ar)
            {
                String content = String.Empty;            StateObject state = (StateObject)ar.AsyncState;
                Socket handler = state.workSocket;             int bytesRead = handler.EndReceive(ar);            if (bytesRead > 0)
                {
                    string sg = Encoding.ASCII.GetString(state.buffer);
                    if (sg.Contains("That"))
                    {
                        //验证为合法
                    }
                    else if (sg.Contains("This"))
                    {
                        //验证为非法
                        handler.Shutdown(SocketShutdown.Both);
                        handler.Close();
                    }
                    else
                    {
                        Console.WriteLine(sg);                }
                }
            }        public static int Main(String[] args)
            {
                StartListening();
                return 0;
            }
        }
    }
    客户端1:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Net;
    using System.Net.Sockets;namespace client
    {
        public partial class Form1 : Form
        {
            static IPEndPoint localip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10001);
            TcpClient client = new TcpClient(localip);        public Form1()
            {
                InitializeComponent();
            }        
            private void button1_Click(object sender, EventArgs e)
            {
                client.BeginConnect(IPAddress.Parse("127.0.0.1"),20000, new AsyncCallback(ConnectCallback), client);
            }
            public static void ConnectCallback(IAsyncResult ar)
            {
                TcpClient s = (TcpClient)ar.AsyncState;
                s.EndConnect(ar);
                StateObject so2 = new StateObject();
                so2.workSocket = s;
                byte[] buff = Encoding.ASCII.GetBytes("This");
                s.Client.BeginSend(buff, 0, buff.Length, 0,
                                      new AsyncCallback(Send_Callback), so2);  
            }        public static void Send_Callback(IAsyncResult ar)
            {
                StateObject so = (StateObject)ar.AsyncState;
                TcpClient s = so.workSocket;            int send = s.Client.EndSend(ar);        }        private void button2_Click(object sender, EventArgs e)
            {
               
     
            }        public class StateObject
            {
                public TcpClient workSocket = null;
                public const int BUFFER_SIZE = 1024;
                public byte[] buffer = new byte[BUFFER_SIZE];
                public StringBuilder sb = new StringBuilder();
            }        private void button2_Click_1(object sender, EventArgs e)
            {
                byte[] buff = Encoding.ASCII.GetBytes("asd");
                client.Client.Send(buff);
            }
        }
    }
    客户端2:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Net;
    using System.Net.Sockets;namespace client
    {
        public partial class Form1 : Form
        {
            static  IPEndPoint localip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10000);
            TcpClient client = new TcpClient(localip);        public Form1()
            {
                InitializeComponent();
            }
            public static void ConnectCallback(IAsyncResult ar)
            {
                TcpClient s = (TcpClient)ar.AsyncState;
                s.EndConnect(ar);
                StateObject so2 = new StateObject();
                so2.workSocket = s;
                byte[] buff = Encoding.ASCII.GetBytes("This");
                s.Client.BeginSend(buff, 0, buff.Length, 0,
                                      new AsyncCallback(Send_Callback), so2);
            }        public static void Send_Callback(IAsyncResult ar)
            {
                StateObject so = (StateObject)ar.AsyncState;
                TcpClient s = so.workSocket;            int send = s.Client.EndSend(ar);        }        private void button2_Click(object sender, EventArgs e)
            {
                //TcpClient client = new TcpClient(IPAddress.Parse("127.0.0.1"), 10001);
                client.BeginConnect(IPAddress.Parse("127.0.0.1"), 20000, new AsyncCallback(ConnectCallback), client);
            }
            public class StateObject
            {
                public TcpClient workSocket = null;
                public const int BUFFER_SIZE = 1024;
                public byte[] buffer = new byte[BUFFER_SIZE];
                public StringBuilder sb = new StringBuilder();
            }        private void button1_Click(object sender, EventArgs e)
            {
                byte[] buff = System.Text.Encoding.Default.GetBytes("asd");
                client.Client.Send(buff);
            }    }
    }
    本来想让客户端1(非法用户)CONNECT后,通过服务器验证(“THIS”),关闭掉SOCKET,让服务器不与它进行通信;BUTTON2_CLICK事件用来确认是否断开。
    让客户端2(合法用户)CONNECT服务器后,可通过BUTTON2_CLICK事件发信息给服务器;
    但好像关闭掉SOCKET后,连合法用户都一起断开连接了!请大家看看
      

  14.   

    SOCKET类中有提供第三次握手,发暗号的方法吗?好像连接就是CONNECT方法,具体怎么三次连接的这个过程,好像并没有可控制的办法吧!?
      

  15.   

    我看了你写的,先不说代码所含的问题毕竟只是个测试,按流程来说,服务端和客户端没有在一个方法上阻塞,这样当服务端关闭该连接后,客户端不会有任何反应。socket需要在receive上阻塞,这样当这个连接失效后,会有异常。你的服务端在接收到一个socket第一条消息后,没有再去接收第二条,这样即使你那个正常的客户端再次发送,服务端也无法收到。
    实际上现在验证这个问题对你来说是个遥远的问题,这个问题应该在已经建立比较稳定可靠的socket通信的基础上,再去进一步加固其安全性。
      

  16.   

    谢谢,经过不懈努力!终于可以实现这种验证和断开的大体功能了,如果验证错误,服务器将不会与错误客户端进行通信,但同时不影响服务器与其它客户端的连接和通信。
    但还有一个小问题:假如是合法用户偶然输错密码了,验证错误了,想再连一次,却始终报错,而且错误不一样:点击第一次时出现“在一个已经连接的套接字上做了一个连接请求”;点击第二次时出现“无法访问已释放的对象。”
    服务器端程序:
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;namespace ConsoleApplication2
    {
        // State object for reading client data asynchronously
        public class StateObject
        {
            // Client  socket.
            public Socket workSocket = null;
            // Size of receive buffer.
            public const int BufferSize = 1024;
            // Receive buffer.
            public byte[] buffer = new byte[BufferSize];
            // Received data string.
            public StringBuilder sb = new StringBuilder();
        }    public class AsynchronousSocketListener
        {
            // Thread signal.
            //通知一个或多个正在等待的线程已发生事件ManualResetEvent
            public static ManualResetEvent allDone = new ManualResetEvent(false);        public AsynchronousSocketListener()
            {
            }        public static void StartListening()
            {
                // Data buffer for incoming data.
                byte[] bytes = new Byte[1024];
                IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"),2230);
                Socket listener = new Socket(AddressFamily.InterNetwork,
                    SocketType.Stream, ProtocolType.Tcp);
                try
                {
                    listener.Bind(localEndPoint);
                    listener.Listen(500);                while (true)
                    {
                        // Set the event to nonsignaled state.
                        allDone.Reset();   //将事件状态设置为非终止状态,导致线程阻止。                    Console.WriteLine("Waiting for a connection...");
                        listener.BeginAccept(
                            new AsyncCallback(AcceptCallback),
                            listener);                    allDone.WaitOne();//阻止当前线程,直到当前 WaitHandle 收到信号。 
                    }            }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }            Console.WriteLine("\nPress ENTER to continue...");
                Console.Read();        }        public static void AcceptCallback(IAsyncResult ar)
            {
                allDone.Set();//将事件状态设置为终止状态,允许一个或多个等待线程继续。
                Socket listener = (Socket)ar.AsyncState; //获取用户定义的对象,它限定或包含关于异步操作的信息。
                Socket handler = listener.EndAccept(ar);            // Create the state object.
                StateObject state = new StateObject();
                state.workSocket = handler;
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReadCallback), state);
            }        public static void ReadCallback(IAsyncResult ar)
            {
                String content = String.Empty;            // Retrieve the state object and the handler socket
                // from the asynchronous state object.
                StateObject state = (StateObject)ar.AsyncState;
                Socket handler = state.workSocket;            // Read data from the client socket. 
                int bytesRead = handler.EndReceive(ar);            if (bytesRead > 0)
                {
                    // There  might be more data, so store the data received so far.
                    string aa = System.Text.Encoding.Default.GetString(state.buffer, 0, bytesRead);
                    if (aa.Contains("This"))
                    {
                        Console.WriteLine(aa);
                        handler.Shutdown(SocketShutdown.Both);
                        //handler.Disconnect(true);
                        handler.Close();
                        try
                        {
                            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                            new AsyncCallback(ReadCallback), state);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.ToString());
                        }
                        //Send(handler, content);
                    }
                    else if (aa.Contains("That"))
                    {
                        // Not all data received. Get more.
                        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReadCallback), state);
                        Console.WriteLine(aa);
                    }
                    else
                    {
                        Console.WriteLine(aa);
                        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReadCallback), state);
                    }
                }
            }        public static int Main(String[] args)
            {
                StartListening();
                return 0;
            }
        }
    }
    验证错误客户端程序:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;namespace clientform
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }                public AsynchronousClient client_soc = new AsynchronousClient();
            private void button1_Click(object sender, EventArgs e)
            {
                
                try
                {
                    client_soc.StartClient();
                }
                catch (Exception ee)
                {
                    textBox1.Text = ee.ToString();
                    //client_soc.client.Disconnect(true);
                    client_soc.client.Close();
                    //client_soc.client.
                }
            }     public class StateObject
         {
            // Client socket.
            public Socket workSocket = null;
            // Size of receive buffer.
            public const int BufferSize = 256;
            // Receive buffer.
            public byte[] buffer = new byte[BufferSize];
            // Received data string.
            public StringBuilder sb = new StringBuilder();
        }    public class AsynchronousClient
        {
            // The port number for the remote device.
            private const int port = 2230;//2230        // ManualResetEvent instances signal completion.
            private static ManualResetEvent connectDone =
                new ManualResetEvent(false);
            private static ManualResetEvent sendDone =
                new ManualResetEvent(false);
            private static ManualResetEvent receiveDone =
                new ManualResetEvent(false);        // The response from the remote device.
            private static String response = String.Empty;        public Socket client = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);        public void StartClient()
            {
                    IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
                    client.BeginConnect(remoteEP,
                        new AsyncCallback(ConnectCallback), client);
                    connectDone.WaitOne();                // Send test data to the remote device.
                    Send(client, "This");
                    sendDone.WaitOne();
                    Console.WriteLine("Response received : {0}", response);
            }        private static void ConnectCallback(IAsyncResult ar)
            {
                try
                {
                    // Retrieve the socket from the state object.
                    Socket client2 = (Socket)ar.AsyncState;                // Complete the connection.
                    client2.EndConnect(ar);                Console.WriteLine("Socket connected to {0}",
                        client2.RemoteEndPoint.ToString());                // Signal that the connection has been made.
                    connectDone.Set();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }        public  void Send(Socket client2, String data)
            {
                // Convert the string data to byte data using ASCII encoding.
                byte[] byteData = Encoding.ASCII.GetBytes(data);            // Begin sending the data to the remote device.
                client2.BeginSend(byteData, 0, byteData.Length, 0,
                    new AsyncCallback(SendCallback), client2);
            }        private static void SendCallback(IAsyncResult ar)
            {
                try
                {
                    // Retrieve the socket from the state object.
                    Socket client2 = (Socket)ar.AsyncState;                // Complete sending the data to the remote device.
                    int bytesSent = client2.EndSend(ar);
                    //("Sent {0} bytes to server.", bytesSent);                // Signal that all bytes have been sent.
                    sendDone.Set();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
        }
    }
      

  17.   

    恭喜,呵呵。客户端出现你说的情况,应该采用如下方式解决:客户端需要beginreceive,并在beginreceive的回调方法中继续beginreceive,这样服务端关闭该连接后,客户端在receive回调方法会捕获到异常,该连接已经不能正常发送,可以调用close关闭掉,然后再次new socket进行连接。
    你这个代码中捕获到的的第一个错误是因为socket未释放,第二个错误是因为socket释放了,看一下button的点击事件就可以知道原因。
      

  18.   

    确实加了个beginreceive后有反应了,服务器端断开的时候这边接收到0字节。然后我CLOSE掉,确实不会报第一个错误了,但是直接报“无法访问已释放的对象。”private static void Receive(Socket client2)
            {
                try
                {
                    // Create the state object.
                    StateObject state = new StateObject();
                    state.workSocket = client2;                // Begin receiving the data from the remote device.
                    client2.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReceiveCallback), state);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }        private static void ReceiveCallback(IAsyncResult ar)
            {
                try
                {
                    // Retrieve the state object and the client socket 
                    // from the asynchronous state object.
                    StateObject state = (StateObject)ar.AsyncState;
                    Socket client2 = state.workSocket;                // Read data from the remote device.
                    int bytesRead = client2.EndReceive(ar);                if (bytesRead > 0)
                    {
                        // There might be more data, so store the data received so far.
                        //state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
                        string aa = System.Text.Encoding.Default.GetString(state.buffer, 0, bytesRead);
                        if (aa.Equals("asd"))
                        {
                            client2.Close();
                        }
                        else
                        {
                            // Get the rest of the data.
                            client2.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                                new AsyncCallback(ReceiveCallback), state);
                        }
                    }
                    else
                    {
                        // All the data has arrived; put it in response.
                        if (state.sb.Length > 1)
                        {
                            response = state.sb.ToString();
                        }
                        // Signal that all bytes have been received.
                        receiveDone.Set();
                        client2.Close();                }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
      

  19.   

    我把SOCKET在全局定义,点击连接后才实例化终于解决了报错问题。 public AsynchronousClient client_soc ;
            private void button1_Click(object sender, EventArgs e)
            {
                //AsynchronousClient client_soc = new AsynchronousClient();
                client_soc = new AsynchronousClient();
                try
                {
                    client_soc.StartClient();
                }
                catch (Exception ee)
                {
                    textBox1.Text = ee.ToString();
                    //client_soc.client.Disconnect(true);
                    client_soc.client.Close();
                    //client_soc.client.
                }
            }
    但这里判断是否断开的方式是在客户端的ReceiveCallback函数中判断收到字节是否为0,有没有除断开连接时可能收到0字节外,还有没其他情况也会受到0字节呢?这样是否可能导致误将客户端SOCKET关闭呢!?private static void ReceiveCallback(IAsyncResult ar)
            {
                try
                {
                    // Retrieve the state object and the client socket 
                    // from the asynchronous state object.
                    StateObject state = (StateObject)ar.AsyncState;
                    Socket client2 = state.workSocket;                // Read data from the remote device.
                    int bytesRead = client2.EndReceive(ar);                if (bytesRead > 0)
                    {
                        // There might be more data, so store the data received so far.
                        //state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
                        string aa = System.Text.Encoding.Default.GetString(state.buffer, 0, bytesRead);
                        if (aa.Equals("asd"))
                        {
                            client2.Close();
                        }
                        else
                        {
                            // Get the rest of the data.
                            client2.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                                new AsyncCallback(ReceiveCallback), state);
                        }
                    }
                    else
                    {
                        // All the data has arrived; put it in response.
                        if (state.sb.Length > 1)
                        {
                            response = state.sb.ToString();
                        }
                        // Signal that all bytes have been received.
                        receiveDone.Set();
                        client2.Close();
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
      

  20.   

    使用DISCONNECT或CLOSE方法,连接方会通过RECEIVE受到0字节长度数据,还有没其他的情况下可能收到0字节长度的数据啊?