当前位置:  开发笔记 > 编程语言 > 正文

Java,服务器客户端TCP通信以RST结束

如何解决《Java,服务器客户端TCP通信以RST结束》经验,为你挑选了1个好方法。

我想知道这是否正常.因为没有错误,连接应该通过以下方式终止:

FIN ->
<- ACK
<- FIN
ACK ->

我在TCP连接结束时得到这个(通过SSL,但我也得到它未加密):

         From     To
1494    server  client  TCP search-agent > 59185 [PSH, ACK] Seq=25974 Ack=49460 Win=63784 Len=50
1495    client  server  TCP 59185 > search-agent [ACK] Seq=49460 Ack=26024 Win=63565 Len=0
1496    client  server  TCP 59185 > search-agent [PSH, ACK] Seq=49460 Ack=26024 Win=63565 Len=23
1497    client  server  TCP 59185 > search-agent [FIN, ACK] Seq=49483 Ack=26024 Win=63565 Len=0
1498    server  client  TCP search-agent > 59185 [PSH, ACK] Seq=26024 Ack=49484 Win=63784 Len=23
1499    client  server  TCP 59185 > search-agent [RST, ACK] Seq=49484 Ack=26047 Win=0 Len=0

客户端正常退出并到达socket.close,不应该正常关闭连接,没有重置?

我在谷歌上找不到关于java的TCP流的任何信息......

这是我的代码:

服务器:

package Security;

import java.io.*;
import java.net.*;

import javax.net.ServerSocketFactory;
import javax.net.ssl.*;
import java.util.*;

public class SSLDemoServer
{
    private static ServerSocket serverSocket;
    private static final int PORT = 1234;

    public static void main(String[] args) throws IOException
    {
        int received = 0;
        String returned; 
        ObjectInputStream input = null;
        PrintWriter output = null;
        Socket client;

        System.setProperty("javax.net.ssl.keyStore", "key.keystore");
        System.setProperty("javax.net.ssl.keyStorePassword", "vwpolo");
        System.setProperty("javax.net.ssl.trustStore", "key.keystore");
        System.setProperty("javax.net.ssl.trustStorePassword", "vwpolo");

        try
        {
            System.out.println("Trying to set up server ...");
            ServerSocketFactory factory = SSLServerSocketFactory.getDefault();
            serverSocket = factory.createServerSocket(PORT);

            System.out.println("Server started!\n");
        }
        catch (IOException ioEx)
        {
            System.out.println("Unable to set up port!");
            ioEx.printStackTrace();
            System.exit(1);
        }

        while(true)
        {
            client = serverSocket.accept();
            System.out.println("Client trying to connect...");

            try
            {
                System.out.println("Trying to create inputstream...");
                input = new ObjectInputStream(client.getInputStream());
                System.out.println("Trying to create outputstream...");
                output = new PrintWriter(client.getOutputStream(), true);
                System.out.println("Client successfully connected!");

                while( true )
                {
                    received = input.readInt();
                    returned = Integer.toHexString(received);
                    System.out.print(" " + received);
                    output.println(returned.toUpperCase());
                }
            }
            catch(SSLException sslEx)
            {
                System.out.println("Connection failed! (non-SSL connection?)\n");
                client.close();
                continue;
            }
            catch(EOFException eofEx)
            {
                System.out.println("\nEnd of client data.\n");
            }
            catch(IOException ioEx)
            {
                System.out.println("I/O problem! (correct inputstream?)");
            }

            try {
                input.close();
                output.close();
            }
            catch (Exception e) {
            }
            client.close();
            System.out.println("Client closed.\n");
        }
    }
}

客户:

package Security;

import java.io.*;
import java.net.*;
import javax.net.ssl.*;

import java.util.*;

public class SSLDemoClient
{
    private static InetAddress host;
    private static final int PORT = 1234;

    public static void main(String[] args)
    {
        System.setProperty("javax.net.ssl.keyStore", "key.keystore");
        System.setProperty("javax.net.ssl.keyStorePassword", "vwpolo");
        System.setProperty("javax.net.ssl.trustStore", "key.keystore");
        System.setProperty("javax.net.ssl.trustStorePassword", "vwpolo");

        System.out.println("\nCreating SSL socket ...");
        SSLSocket socket = null;
        try
        {
            host = InetAddress.getByName("192.168.56.101");
            SSLSocketFactory factory = (SSLSocketFactory)
            SSLSocketFactory.getDefault();
            socket = (SSLSocket) factory.createSocket(host, PORT);
            socket.startHandshake();
        }
        catch(UnknownHostException uhEx)
        {
            System.out.println("\nHost ID not found!\n");
            System.exit(1);
        }
        catch(SSLException sslEx)
        {
            System.out.println("\nHandshaking unsuccessful ...");
            System.exit(1);
        } 
        catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("\nHandshaking succeeded ...\n");

        SSLClientThread client = new SSLClientThread(socket);
        SSLReceiverThread receiver = new SSLReceiverThread(socket);

        client.start();
        receiver.start();

        try
        {
            client.join();
            receiver.join();
            System.out.println("Trying to close...");
            socket.close();
        }
        catch(InterruptedException iEx)
        {
            iEx.printStackTrace();
        } 
        catch(IOException ioEx)
        {
            ioEx.printStackTrace();
        }

        System.out.println("\nClient finished.");
    }
}


class SSLClientThread extends Thread
{
    private SSLSocket socket;

    public SSLClientThread(SSLSocket s)
    {
        socket = s;
    }

    public void run() 
    {
        try
        {
            ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());

            for( int i = 1; i < 1025; i++)
            {
                output.writeInt(i);
                sleep(10);
                output.flush();
            } 

            output.flush();
            sleep(1000);
            output.close();
        }
        catch(IOException ioEx)
        {
            System.out.println("Socket closed or unable to open socket.");
        }
        catch(InterruptedException iEx)
        {
            iEx.printStackTrace();
        }
    }
}


class SSLReceiverThread extends Thread
{
    private SSLSocket socket;

    public SSLReceiverThread(SSLSocket s)
    {
        socket = s;
    }

    public void run()
    {
        String response = null;
        BufferedReader input = null;

        try
        {
            input = new BufferedReader(
                    new InputStreamReader(socket.getInputStream()));

            try
            {
                response = input.readLine();
                while(!response.equals(null)) 
                {
                    System.out.print(response + " ");
                    response = input.readLine();
                } 
            }
            catch(Exception e)
            {
                System.out.println("\nEnd of server data.\n");
            }    

            input.close();

        }
        catch(IOException ioEx)
        {
            ioEx.printStackTrace();
        }
    }
}

非常感谢,在非SSL连接上,我现在可以在没有重置的情况下获得良好的有序连接关闭.

但显然这种方法不受支持SSLSocket?当我在我的SSL客户端中尝试它时,我得到以下异常:

Exception in thread "Thread-0" java.lang.UnsupportedOperationException: The method shutdownOutput() is not supported in SSLSocket
    at com.sun.net.ssl.internal.ssl.BaseSSLSocketImpl.shutdownOutput(Unknown Source)
    at Security.SSLClientThread.run(SSLDemoClient.java:99)

我的新代码如下所示:

package Security;

import java.io.*;
import java.net.*;

import javax.net.SocketFactory;
import javax.net.ssl.*;

public class SSLDemoClient
{
    private static InetAddress host;
    private static Socket socket;
    private static final int PORT = 1234;

    public static void main(String[] args)
    {
        System.setProperty("javax.net.ssl.keyStore", "key.keystore");
        System.setProperty("javax.net.ssl.keyStorePassword", "vwpolo");
        System.setProperty("javax.net.ssl.trustStore", "key.keystore");
        System.setProperty("javax.net.ssl.trustStorePassword", "vwpolo");

        System.out.println("\nCreating SSL socket ...");

        try
        {
            host = InetAddress.getByName("192.168.56.101");
            SocketFactory socketFactory = SSLSocketFactory.getDefault();
            socket = socketFactory.createSocket(host, PORT);
        }
        catch(UnknownHostException uhEx)
        {
            System.out.println("\nHost ID not found!\n");
            System.exit(1);
        }
        catch(SSLException sslEx)
        {
            System.out.println("\nHandshaking unsuccessful ...");
            System.exit(1);
        } 
        catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("\nHandshaking succeeded ...\n");

        SSLClientThread client = new SSLClientThread(socket);
        SSLReceiverThread receiver = new SSLReceiverThread(socket);

        client.start();
        receiver.start();

        try
        {
            client.join();
            receiver.join();
            System.out.println("Trying to close...");

            socket.close();
        }
        catch(InterruptedException iEx)
        {
            iEx.printStackTrace();
        } 
        catch(IOException ioEx)
        {
            ioEx.printStackTrace();
        }

        System.out.println("\nClient finished.");
    }
}


class SSLClientThread extends Thread
{
    private Socket socket;

    public SSLClientThread(Socket s)
    {
        socket = s;
    }

    public void run() 
    {
        try
        {
            ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());

            for( int i = 1; i < 1025; i++)
            {
                output.writeInt(i);
                sleep(10);
                output.flush();
            } 

            output.flush();
            sleep(1000);
            socket.shutdownOutput();
        }
        catch(IOException ioEx)
        {
            System.out.println("Socket closed or unable to open socket.");
        }
        catch(InterruptedException iEx)
        {
            iEx.printStackTrace();
        }
    }
}


class SSLReceiverThread extends Thread
{
    private Socket socket;

    public SSLReceiverThread(Socket s)
    {
        socket = s;
    }

    public void run()
    {
        String response = null;
        BufferedReader input = null;

        try
        {
            input = new BufferedReader(
                    new InputStreamReader(socket.getInputStream()));

            try
            {
                response = input.readLine();
                while(!response.equals(null)) 
                {
                    System.out.print(response + " ");
                    response = input.readLine();
                } 
            }
            catch(Exception e)
            {
                System.out.println("\nEnd of server data.\n");
            }    

            socket.shutdownInput();

        }
        catch(IOException ioEx)
        {
            ioEx.printStackTrace();
        }
    }
}

我没有正确使用它吗?或者我的SSLSocket不正确?因为使用非SSL连接没有问题.



1> caf..:

您的数据包日志显示客户端正在发送其最后一位数据,并通知服务器连接已关闭.

然后服务器发回它的最后一位数据(可能是最后转换的整数).客户端响应a RST,表示客户端套接字因读取写入而关闭- 客户端说"抱歉,我没有抓到最后一点数据,我不再听了".

我不是Java大师,但似乎调用.close()套接字的OutputStream方法导致在.close()套接字本身上调用该方法.你真正希望在这里发生的事情(在客户端写完最后一个整数之后)是shutdownOutput()在socket上调用该方法.

推荐阅读
sx-March23
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有