我的应用程序继续加载(圆圈光标)。这是我的代码
public class ControllerW {
@FXML
private Label statusLbl, timeLbl, textLbl;
@FXML
private Button exitBtn, linkBtn;
private ServerSocket serverSckt;
private Socket clientSckt;
DataInputStream dis;
String text;
@FXML
private void exit() {
System.exit(0);
}
@FXML
private void linkAndroid() {
try {
serverSckt = new ServerSocket(5678);
statusLbl.setText("Server started");
clientSckt = serverSckt.accept();
statusLbl.setText("client connected successfully");
dis = new DataInputStream(clientSckt.getInputStream());
text = dis.toString();
textLbl.setText(text);
} catch (Exception e) {
statusLbl.setText("No connection on port 5678");
e.printStackTrace();
}
}
}
我是socket编程的新手,如果我的代码有任何问题,有人可以帮助我吗
答案 0 :(得分:1)
您的应用程序停止响应,因为它没有线程化。如果没有多线程,您的应用程序将在您点击“链接”按钮时“停止”,因为拨打ServerSocket#accept
。
原因是accept
方法的阻止特性。直到另一个套接字连接,ServerSocket
正在等待并保持当前线程“暂停”。可以把它想象成一个与此类似的内在循环:
while(!isConnected())
{
// check if there is a new request
}
想象一下,没有客户会连接。这个循环怎么会停止?从不。
可能的解决方法是线程整个UI部分或“数据模型”部分。
我首选的方法是创建一个只处理ServerSocket#accept
方法的自定义类,并将传入的连接委托给另一个负责其余部分的线程。我这样做是为了随时保持我的服务器可访问,这可能不是解决问题的最佳方法。
这就是我的帮助程序类通常的样子:
<强> ClientAccepter.java:强>
public class ClientAccepter
implements Runnable
{
// the ServerSocket
private final ServerSocket server;
// ExecutorServices ease the pain of threading your application quite a lot
private final ExecutorService es = Executors.newCachedThreadPool();
private boolean isAlive = true;
public ClientAccepter( ServerSocket server )
{
this.server = server;
}
@Override
public void run()
{
//This is where you specify your desired behaviour.
//Example:
while ( isAlive )
{
try
{
es.execute( new ClientHandler( server.accept() ) );
}
catch ( IOException e )
{
e.printStackTrace();
}
}
}
}
对这样一个类的调用可能如下所示:
<强> Server.java:强>
public class Server
{
//ExecutorServices are the best and easy to use.
private static ExecutorService serverThreader = Executors.newSingleThreadExecutor();
public static void main( String[] args )
{
try
{
serverThreader.execute( new ClientAccepter( new ServerSocket( 8080 ) ) );
}
catch ( IOException e )
{
e.printStackTrace();
//further exception handling.
}
}
}
公平地说,这可能不是最好的方法,但它是我处理阻止操作的首选方式。您应该考虑使用orcale concurrency tutorial并明确地查看ExecutorServices
,因为它们是一个非常容易处理线程池的框架。
特别是对于JavaFX,有一个concurrency tutorial。
答案 1 :(得分:0)
首先使用GUI / JFX线程运行套接字。所以accept()
会阻止它(用户界面不负责任,你知道的数据圈)。
您需要使用另一个线程运行IO /套接字。但要注意,您需要使用UI线程更改UI内容。 (例如,textLbl.setText(text);
如果从另一个线程直接调用则可能失败)
此行text = dis.toString();
也是无意义的,你应该从客户端发送一个字符串?因此,请使用readLine()
中的(推荐)BufferedReader
方法,而不是DataInputStream
。 (readUTF
也可能来自DataInputStream
)。