简体   繁体   中英

The scanner hasNext() , but can't read with nextLine()

I am trying o make a multithreaded server (so it could be accessed by more users at the same time). I manage to establish a connection between the user and the server, .isConnected() returns true, hasNext() returns true, but the program stops at .nextLine() . Why ? First part of server:

import java.awt.Dimension;
import java.io.*;
import java.net.*;
import java.util.*;

import javax.swing.JFrame;
import javax.swing.JTextField;
public class Testserver {
    static int nr=0,i;
    String mass;
    boolean ok;
    public static ArrayList<Socket> Connection=new ArrayList<Socket>();
    public static ArrayList<String> Users=new ArrayList<String>();
    public static ArrayList<Thread> Tests=new ArrayList<Thread>();
    public static JTextField user;
    public static void main(String[] args) throws Exception{
        JFrame f=new JFrame();
        user=new JTextField("",20);
        Dimension us=user.getPreferredSize();
        user.setBounds(500,350,us.width,us.height);
        f.setTitle("Testserver");
        f.setSize(1200,820);
        f.setLocationRelativeTo(null);
        f.setResizable(false);
        f.setVisible(true);
        f.setLayout(null);
        f.add(user);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        try{
            ServerSocket Srv=new ServerSocket(201);
            while(true){
                Socket Sock=Srv.accept();
                nr=Connection.size();
                if(nr<20){
                    Connection.add(Sock);
                    Tests.add(new Thread(new Testserver_run(Sock,nr)));
                    Tests.get(nr).start();
                }
                else{
                    PrintStream ps=new PrintStream(Sock.getOutputStream());
                    ps.println("server full");
                    ps.flush();
                }
            }
        } catch(Exception e){
        }
    }
}

Second part:

import java.io.*;
import java.net.*;
import java.util.*;
public class Testserver_run implements Runnable{
    Socket Sock;
    Scanner in;
    PrintWriter out;
    String mass="9";
    int nr=Testserver.nr,id;
    public Testserver_run(Socket S,int idd){
        this.Sock=S;
        this.id=idd;
    }
    public boolean checkconnection() throws IOException{
        Testserver.user.setText("6");
        if(!Sock.isConnected()){
            Testserver.user.setText("7");
            Testserver.Connection.remove(id);
            Testserver.Users.remove(id);
            Testserver.Tests.remove(id);
            return false;
        }
        else return true;
    }
    public void run(){
        Testserver.user.setText("1");
        try{
            in=new Scanner(Sock.getInputStream());
            out=new PrintWriter(Sock.getOutputStream());
            Testserver.user.setText("2");
            try{
                while(checkconnection()){
                    if(in.hasNext()){
                        Testserver.user.setText("5");
                        mass=in.nextLine();
                        Testserver.user.setText(mass);
                    }
                }
            }
            finally{
                Testserver.user.setText("3");
                Sock.close();
            }
        } catch(Exception e){

        }
    }
}

Client part:

import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.Scanner;
import java.awt.Dimension;
import java.awt.event.*;
public class Testuser{
    public static JTextField user;
    public static Socket S;
    public static PrintWriter out;
    public static Scanner in;
    public static String mess;
    public static void main(String[] args)  throws Exception{
//      Testuser Test=new Testuser();
        user=new JTextField("",20);
        Dimension us=user.getPreferredSize();
        user.setBounds(500,350,us.width,us.height);
        user.addKeyListener(new Al1());
        JFrame f=new JFrame();
        f.setTitle("Test");
        f.setSize(1200,820);
        f.setLocationRelativeTo(null);
        f.setResizable(false);
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(null);
        f.add(user);
        f.setFocusable(true);
        try {
            S=new Socket("localhost",201);
            out = new PrintWriter(S.getOutputStream(), true);
            in = new Scanner(
                    new InputStreamReader(S.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Don't know localhost");
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Cannot open IO");
            System.exit(1);
        }
    }
    public static void send(String mess,PrintWriter out) {
        out.write(mess);
        out.flush();
    }
    public static class Al1 extends KeyAdapter{
        int key;
        public void keyPressed(KeyEvent e){
            key=e.getKeyCode();
            if(key==KeyEvent.VK_ENTER){
                    mess = user.getText();
                    if(mess.equals("stop")){
                        try{
                            S.close();
                        }catch(Exception exc){

                        }
                    }else{
                        send(mess,out);
                    }
                }
            }
    }
}

Thanks in advance !

.isConnected() returns true, hasNext() returns true, but the program stops at .nextLine() . Why ?

For a start isConnected() only means that the socket has been connected at some point in the past. It doesn't tell you if the connection is still viable.

One scenario where hasNext() returns true but nextLine() blocks is when there are characters to be read, but the "end of line" marker has not yet been read. The hasNext() result is telling you that next() will give you a token. It doesn't tell you if nextLine() will succeed. If you want to know that, call hasNextLine() ... but beware that that will also block waiting for a line.

So, to bring this back to your current problem, I can't see where you are writing end-of-line markers. On the client side. Indeed, I can't see where you are explicitly writing any form of inter-token stuff. If you are going to use Scanner , you need to read the javadocs carefully and design your "protocol" to match the capabilities of the class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM