套接字的多线程问题

Posted

技术标签:

【中文标题】套接字的多线程问题【英文标题】:Multithreading issue with sockets 【发布时间】:2016-12-27 21:16:36 【问题描述】:

我目前正在制作一个允许两个玩家通过插座的棋盘游戏。我也在尝试添加游戏聊天,但我需要一种方法让 Frame 类正常运行(Jbuttons、在 jscroll 区域中输入文本等),但也需要发送和查找传入的对象。我认为实现 runnable 将是最好的选择。 这是我的运行方法:

public void run() 
    while(running)
        Object obj = null;
        try 
            obj = connection.receiveObjects();
         catch (ClassNotFoundException) 
            e.printStackTrace();
         catch (IOException e)
            e.printStackTrace();
            running = false;
        if(obj != null)
            if(obj instanceof String)
                showMessage((String)obj);
            
        
    


我的连接类只是一个服务器或客户端,并使用这些方法:

public void sendObjects(Object obj) throws IOException
        output.writeObject(obj);
        output.flush();

   
public Object receiveObjects() throws IOException, ClassNotFoundException
        return input.readObject();

在我调用的 Frame 类的构造函数中

Thread thread = new Thread(this);  
thread.start();

希望run方法不会干扰actionPerformed方法。但令我沮丧的是,当我单击一个 jbutton(它所做的只是调用 send() 方法)时,程序冻结了,没有发送任何内容。

这是其他必要的代码:

private JTextArea textBox;
private JScrollPane pane;
private JTextArea userText;
private JScrollPane userPane;



private void send()
    String message = "YOU- " + userText.getText();
    userText.setText("");
    String totalMessage = textBox.getText();
    textBox.setText(totalMessage + "/n" + message);
    try 
        connection.sendObjects(message);
     catch (IOException e) 
        e.printStackTrace();
    


public void showMessage(String s)
    String totalMessage = "Opponent- " + textBox.getText();
    textBox.setText(totalMessage + "/n" + s);

我的希望是,一旦我开始聊天,我还可以添加发送片段并调用其他方法来完成我需要的所有其他事情(通过 instanceof)。我可能可以创建一个单独的类来实现 runnable 来处理数据传输,但我希望我可以在一个类中完成所有这些,并且不明白为什么我不能。我确实花了至少一个半小时来查找多线程,但我无法弄清楚我的问题。如果我正在查看任何明显的东西,我深表歉意,但多线程和套接字远远超出了我的舒适区和 AP Comp sci 课程教育。

【问题讨论】:

您应该单独捕获EOFException,并在捕获时终止读取循环。除了SocketTimeoutException 之外的所有其他IOExceptiions 对连接都是致命的;应该记录;并且还应该终止读取循环。 EOFException?我认为我没有这些,但我会编辑 IOException 的读取循环。 当对等方关闭连接时,您将获得“其中之一”。 @EJP,我经常在这个网站上看到你,所以我想知道你是否知道是什么导致我的发送线程无法发送? 【参考方案1】:

除了 UI 线程,您还需要:

    一个线程持续监听传入数据 一个线程发送数据

你有#1但没有#2,所以修改send()方法如下:

private void send() 
    // Do the UI tasks on the UI thread
    final String message = "YOU- " + userText.getText();
    userText.setText("");
    String totalMessage = textBox.getText();
    textBox.setText(totalMessage + "\n" + message);
    // Start new thread to do the networking (send data)
    new Thread(new Runnable() 
        @Override
        public void run() 
            try 
                connection.sendObjects(message);
             catch (IOException e) 
                e.printStackTrace();
            
        
    ).start();

【讨论】:

哇,3 个线程?我从来没有想过!谢谢!它不再冻结,但似乎从未收到该消息?我在读取循环中放了一个 System.out.print,它只打印一次,表明消息永远不会通过 今天早上经过一些测试后,似乎从未调用 connection.sendObjects(message) 或冻结。我在它之前和之后放了一个 S.O.P,而且只有之前的打印...

以上是关于套接字的多线程问题的主要内容,如果未能解决你的问题,请参考以下文章

C/C++ 中的多线程状态机实现

C++中的多线程,只检查信号量是不是被锁定

Windows 上的 C 中的套接字编程(服务器、使用 select() 和 fd_set 的多线程)

在 C++ 中实现高效的多线程文件 I/O

带有线程池服务器python的套接字

非阻塞套接字多线程接收模型