【问题标题】:java.net.SocketException: Socket is closed TCP Connectionjava.net.SocketException:套接字已关闭 TCP 连接
【发布时间】:2013-04-29 04:04:12
【问题描述】:

做了一些调试,我认为错误发生在下面这个方法中。该方法基本上向服务器发送一个 ID(字符串),服务器在收到此 ID 后查找一条记录,并将其发送回客户端。 ID 显示在用户选择的 GUI JList 中,因此每次用户单击 JList 中的不同 ID 时,此方法由 ListSelectionListener 事件激活。一旦客户端从服务器接收到记录,它就会在 JTextField 中显示它。当用户第一次单击 JList 中的 ID 时,一切都按预期工作。但是当您单击列表中的另一条记录时,我得到了异常:

java.net.SocketException: 套接字已关闭

编辑:现在我得到:

java.net.SocketException:软件导致连接中止:recv failed

客户端程序:

    import java.awt.BorderLayout;
import java.awt.Dimension;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;


public class ClientGUI extends JFrame implements ListSelectionListener{

    //gui components
    JList jlist = null;
    String requestID = null; //Assigned to selected ID in JList. 
    JScrollPane scpane = null;
    JTextField field = null;
    JPanel pane = null;
    DefaultListModel<String> listModel = null;
    ArrayList<String> idList = null;

    //client stuff:
    Socket sock1 = null;
    Socket sock2 = null;
    ObjectInputStream in = null;
    ObjectOutputStream out = null;

    public ClientGUI() throws ClassNotFoundException{
        //get List of IDs from Server1
        try{
            sock1 = new Socket("FahadAhmed-PC", 8889); 
            in = new ObjectInputStream(sock1.getInputStream());
            idList = new ArrayList<String>(29);
            ArrayList<Customer> custList = null;
            custList = (ArrayList<Customer>) in.readObject();
            for(Customer c : custList){
                idList.add(c.getID());
            }

            in.close();
            sock1.close();

            sock2 = new Socket("FahadAhmed-PC", 8888); 
            ArrayList streams = new ArrayList(3); 
            streams.add(out = new ObjectOutputStream(sock2.getOutputStream()));
            streams.add(in = new ObjectInputStream(sock2.getInputStream()));

        }catch(UnknownHostException e) {
            System.err.println("Don't know about host: FahadAhmed-PC");
            System.exit(1);
        }catch(IOException e){
            System.err.println(e);
            System.exit(1);
        }

        //Setup GUI
        jlist = new JList(idList.toArray());
        jlist.setVisibleRowCount(10);
        scpane = new JScrollPane(jlist);
        jlist.addListSelectionListener(this);
        pane = new JPanel(new BorderLayout());
        pane.setPreferredSize(new Dimension(300, 300));
        field = new JTextField(29);
        field.setEditable(false);
        pane.add(scpane, BorderLayout.PAGE_START);
        pane.add(field, BorderLayout.PAGE_END);

        this.setContentPane(pane);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.pack();
        this.setVisible(true);
    }

    public static void main(String args[]) throws ClassNotFoundException{
        ClientGUI gui = new ClientGUI();
    }


    @Override
    public void valueChanged(ListSelectionEvent arg0) {
        if(!arg0.getValueIsAdjusting())
            try {
                System.out.println(jlist.getSelectedValue().toString());
                getRecord(jlist.getSelectedValue().toString());
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }       
    }

    private void getRecord(String getID) throws ClassNotFoundException {
        try{

            //System.out.println(getID + "sent to getRecord method");
            out.writeObject(getID);

            String rec = (String) in.readObject();

            field.setText(rec);
            //in.close();
            //sock2.shutdownInput();
            out.flush();
            //sock2.shutdownOutput();
            //out.close();

        }catch(UnknownHostException e) {
            System.err.println("Don't know about host: FahadAhmed-PC");
            System.exit(1);
        }catch(IOException e){
            System.err.println(e);
            System.exit(1);
        }
    }


}

【问题讨论】:

  • 我尝试通过在上述方法中打开一个新套接字,但出现异常:java.net.ConnectException: Connection denied: connect

标签: java sockets tcp


【解决方案1】:

关闭输入/输出流会关闭套接字。你需要在socket上使用shutdownInput方法,只关闭输入流:

//do sth with fromSocket ... and close it 
socket.shutdownInput();
socket.shutdownOutput();

【讨论】:

  • 我应该在方法中使用它吗?
  • 所以我删除了 in.close 语句并这样做了://in.close(); sock2.shutdownInput(); 问题仍然存在。
  • 哦,我假设您将对输出流执行相同的操作,并使用该添加更新答案。
  • 如果你不关闭流而只是刷新数据怎么办?
  • 只希望我刷新输出流,因为我不能对输入流这样做
【解决方案2】:

关闭输入流或输出流都会关闭套接字,我不知道你为什么在这里关闭任何东西,但这里还有另一个问题。您必须在两端使用相同的ObjectInputStreamObjectOutputStream 来保证套接字的使用寿命。否则,两个对等点将不同步,您将开始看到StreamCorruptedException: invalid type code 之类的内容。

【讨论】:

  • 好的,所以我让它不会在方法内部关闭,而且我很确定我在套接字的整个生命周期中都使用相同的流。取出方法中的close语句,我现在得到一个不同的错误:java.net.SocketException:软件导致连接中止:recv失败
  • 在您发布的代码中,您每次调用 getRecord(). 时都会创建 Object 新流
  • 我有一个问题 - 在我的客户端中,我有一个方法,每次调用它时,i/o 流都会起作用。但是在我的服务器端,我没有循环或任何东西告诉它继续等待客户端发送 ID 请求。它只执行一次,不像我的客户每次调用它都有一个方法。我认为问题可能是因为服务器没有继续写入和读取对象。我如何使它类似于:while(InputStream.hasNext())