我在写一个服务器,请看最下方代码。
添加重启功能时需要结束这个线程,可是如何结束呢?!!!
线程一直在执行socket = serverSocket.accept()interrupt()方法丝毫不起作用,我搞不懂这个方法是干嘛用的。新手所以
大侠们多多指教!package com.socket;
import java.net.*;
/**
*
* @author XHF
*/
public class PrinterServer extends Thread{
/** Creates a new instance of PrinterServer */
int port = 8888; //默认服务器端口
ServerSocket serverSocket = null;
public PrinterServer() {
try {
serverSocket = new ServerSocket(port);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public PrinterServer(int port){
try {
if(port!=0){
this.port = port;
}
serverSocket = new ServerSocket(port);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void run(){
try {
while(true){
Socket socket = null;
socket = serverSocket.accept();
this.threadNum++;
UserThread userThread = new UserThread(socket); //!!!!!!!!!!!!!!!!!
userThread.start();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
添加重启功能时需要结束这个线程,可是如何结束呢?!!!
线程一直在执行socket = serverSocket.accept()interrupt()方法丝毫不起作用,我搞不懂这个方法是干嘛用的。新手所以
大侠们多多指教!package com.socket;
import java.net.*;
/**
*
* @author XHF
*/
public class PrinterServer extends Thread{
/** Creates a new instance of PrinterServer */
int port = 8888; //默认服务器端口
ServerSocket serverSocket = null;
public PrinterServer() {
try {
serverSocket = new ServerSocket(port);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public PrinterServer(int port){
try {
if(port!=0){
this.port = port;
}
serverSocket = new ServerSocket(port);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void run(){
try {
while(true){
Socket socket = null;
socket = serverSocket.accept();
this.threadNum++;
UserThread userThread = new UserThread(socket); //!!!!!!!!!!!!!!!!!
userThread.start();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
楼主【xhf1234】截止到2008-07-19 19:56:10的历史汇总数据(不包括此帖):
发帖的总数量:15 发帖的总分数:890 每贴平均分数:59
回帖的总数量:17 得分贴总数量:0 回帖的得分率:0%
结贴的总数量:15 结贴的总分数:890
无满意结贴数:0 无满意结贴分:0
未结的帖子数:0 未结的总分数:0
结贴的百分比:100.00% 结分的百分比:100.00%
无满意结贴率:0.00 % 无满意结分率:0.00 %
敬礼!
interrupt()会在这抛出异常,所以我改成:
try {
while(true){
Socket socket = null;
socket = serverSocket.accept();
this.threadNum++;
UserThread userThread = new UserThread(socket);
userThread.start();
}
} catch (Exception ex) {
return; //这改了
} 可还是没用
boolean isStop;重启时,令isStop=true; try {
while(!isStop){
Socket socket = null;
socket = serverSocket.accept();
this.threadNum++;
UserThread userThread = new UserThread(socket);
userThread.start();
}
} catch (Exception ex) {
return; //这改了
} 所以你可以定义一个stopService()方法,在这个方法里令isStop=true;
这样 socket = serverSocket.accept();这句代码不会被执行到,下面的线程也不会开始执行了。
因为我这种情况属于无限循环内的阻塞,线程执行到socket = serverSocket.accept(); 停住了,只有accept()方法返回时才向下执行,所以就算在阻塞过程种把while(!isStop)中的isStop为置true也没用,线程根本走不到这一步
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
/**
* @author XHF
*/
public class PrinterServer extends Thread { //** Creates a new instance of PrinterServer */
//文档注释一般加到常量、方法或类的前面,用以说明其使用方法,例如:
/** 服务器默认端口号 */
public static final int DEFAULT_PORT = 8888; //int port = 8888; //默认服务器端口
//ServerSocket serverSocket = null; //实例域如无特殊要求一般声明成私有的
private int port; //默认值的定义放常量中更好
private ServerSocket serverSocket; //引用类型实例域默认值就是 null public PrinterServer() {
this(DEFAULT_PORT); //以默认服务器端口号为参数调用另一构造方法就行
//try {
// serverSocket = new ServerSocket(port);
//} catch (Exception ex) {
// ex.printStackTrace();
//}
} public PrinterServer(int port) {
try {
if (port <= 0 || port > 0xFFFF) { //if (port != 0) {
this.port = DEFAULT_PORT; //如果端口号超出取值范围就使用默认端口号
} else {
this.port = port;
}
this.serverSocket = new ServerSocket(port);
//设置超时值如果 accept 方法调用超过超时值将引发 java.net.SocketTimeoutException
this.serverSocket.setSoTimeout(3000);
} catch (IOException /*Exception*/ ex) { //异常捕获要精细一点
ex.printStackTrace();
}
} private volatile boolean running; //服务器正在运行的标志 public synchronized void startServer() { //启动服务器
this.running = true;
start(); //启动服务器线程
} public synchronized void stopServer() {
this.running = false; //通过此方法将标志变量设置成 false 来停掉服务器
} public void run() {
try {
while (this.running) { //while (true) {
Socket socket = null;
try {
socket = this.serverSocket.accept();
} catch (SocketTimeoutException e) {
e.printStackTrace();
}
if (socket != null) { //防止因超时未获取到 Socket 而出现 NullPointerException
//this.threadNum++;
//UserThread userThread = new UserThread(socket);
//!!!!!!!!!!!!!!!!!
//userThread.start();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}}
光这样不行,accept 方法一样会被阻塞在那儿,直到连接请求到来。
一向都非常认真的解答新手的问题
好人有好报(*^__^*)
去掉e.printStackTrace();可以吧?
可还有个问题,下边是我写的重启服务器的方法
public static void restart(){
server.stopServer();
f.dispose();
try {
Thread.sleep(3000); //可是在这里无论主线程休眠多长时间,重启的时候都会
} catch (InterruptedException ex) { //抛出端口被占用的异常,就是说原来那个还没有完全停止
ex.printStackTrace();
}
f=new ManageFrame();
f.setVisible(true);
server = new PrinterServer();
server.startServer();
}
}
这是什么问题呢?怎么解决?
有一个问题我不大懂。就是ServerSocket这个线程被停止后,它之前创建的若干个UserThread线程是不是也自动停止了?还是得写出停止当前所有线程的代码?如果要的话该怎么写?
解决方法很简单。
让你的停止服务器的程序,链接一下那个端口啊!,哈哈哈!做一个虚假的链接,主程序就继续运行了,也就可以判断你所谓的是否停止的标记了。这个方法可以用来远程关闭服务
public synchronized void stopServer() {
this.running = false;
Socket socket = null;
try {
socket = new Socket("127.0.0.1",port);
} catch (UnknownHostException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
try {
socket.getOutputStream().write(1);
} catch (IOException ex) {
ex.printStackTrace();
}
try {
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
总的代码:
1、
2.ServerSocket:
/*
* UserThread.java
*
* Created on 2008年7月18日, 上午1:25
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/package com.socket;
import com.Main;
import java.io.*;
import java.net.*;
/**
*
* @author XHF
*/
public class UserThread extends Thread{
protected DataInputStream inputStream;
protected DataOutputStream outputStream;
protected Socket socket;
protected boolean running;
/** Creates a new instance of UserThread */
public UserThread(Socket socket) {
try {
this.socket = socket;
inputStream = new DataInputStream(socket.getInputStream());
outputStream = new DataOutputStream(socket.getOutputStream());
this.socket.setSoTimeout(30000);
} catch (IOException ex) {
ex.printStackTrace();
}
}
public synchronized void startThread() {
this.running = true;
start();
}
public synchronized void stopThread() {
this.running = false;
}
public void run(){
String str = null;
try {
str = inputStream.readUTF();
boolean b = this.login(str);
if(b==false)
return;
while(running){
try {
str = inputStream.readUTF();
} catch (SocketTimeoutException e) {
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public boolean login(String str){
String[] s = str.split(",");
String id = s[0];
String pw = s[1];
boolean b =Main.login(id,pw);
if(b==true){ //帐号密码正确
try {
outputStream.writeUTF("a"); //返回信息给客户端a:成功,b:失败
return true;
} catch (IOException ex) {
ex.printStackTrace();
}
}
else{ //帐号密码错误
try {
outputStream.writeUTF("b");
} catch (IOException ex) {
ex.printStackTrace();
}
try {
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return false;
}
return false;
}
}
总的代码:
/*
* PrinterServer.java
*
* Created on 2008年7月18日, 上午1:07
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package com.socket;
import java.io.IOException;
import java.net.*;
/**
*
* @author XHF
*/
public class PrinterServer extends Thread{
/** Creates a new instance of PrinterServer */
//默认端口号
public static final int DEFFAULT_PORT = 8888;
private ServerSocket serverSocket;
private int port;
private volatile boolean running; //服务器正在运行的标志
public PrinterServer() {
this(DEFFAULT_PORT);
}
public PrinterServer(int port){
try {
if(port <= 0 || port > 0xFFFF){
this.port = port;
}
serverSocket = new ServerSocket(port);
//设置超时值如果 accept 方法调用超过超时值将引发 java.net.SocketTimeoutException
// this.serverSocket.setSoTimeout(3000);
} catch (IOException ex) {
ex.printStackTrace();
}
}
public synchronized void startServer() { //启动服务器
this.running = true;
start(); //启动服务器线程
}
public synchronized void stopServer() {
this.running = false;
Socket socket = null;
try {
socket = new Socket("127.0.0.1",port);
} catch (UnknownHostException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
try {
socket.getOutputStream().write(1);
} catch (IOException ex) {
ex.printStackTrace();
}
try {
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void run(){
try {
while(this.running){
Socket socket = null;
try {
socket = serverSocket.accept();
} catch (SocketTimeoutException e) {
//e.printStackTrace();
}
if(socket!=null){
UserThread userThread = new UserThread(socket);
userThread.start();
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
线程就会自动跳出的啦。。同理,如果客户端要退出,则也发一个停止标志给服务器,服务器收到这个标志,就断开相应的客户服务。
我想要一个主动的方法,而不是被动的
为什么我用socket = new Socket("127.0.0.1",port);报错了,原因是端口为0,可是我的ServerSocket构造函数中已经赋值port=8888了啊,为什么?????????
一定要socket = new Socket("127.0.0.1",8888); ??? 大侠们指导一下为什么?
代码如下:
/*
* PrinterServer.java
*
* Created on 2008年7月18日, 上午1:07
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package com.socket;
import java.io.IOException;
import java.net.*;
/**
*
* @author XHF
*/
public class PrinterServer extends Thread{
/** Creates a new instance of PrinterServer */
//默认端口号
public static final int DEFFAULT_PORT = 8888;
private ServerSocket serverSocket;
private int port;
private volatile boolean running; //服务器正在运行的标志
public PrinterServer() {
this(DEFFAULT_PORT);
}
public PrinterServer(int port){
try {
if(port <= 0 || port > 0xFFFF){
this.port = port;
}
serverSocket = new ServerSocket(port);
//设置超时值如果 accept 方法调用超过超时值将引发 java.net.SocketTimeoutException
// this.serverSocket.setSoTimeout(3000);
} catch (IOException ex) {
ex.printStackTrace();
}
}
public synchronized void startServer() { //启动服务器
this.running = true;
start(); //启动服务器线程
}
public synchronized void stopServer() {
this.running = false;
try {
this.serverSocket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
//用socket虚假连接,跳过阻塞,结束进程
Socket socket = null;
try {
socket = new Socket("127.0.0.1",8888); //!!!!!!!!!!!
} catch (UnknownHostException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
try {
socket.getOutputStream().write(1);
} catch (IOException ex) {
ex.printStackTrace();
}
try {
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void run(){
try {
while(this.running){
Socket socket = null;
try {
socket = serverSocket.accept();
} catch (SocketTimeoutException e) {
//e.printStackTrace();
}
if(socket!=null){
UserThread userThread = new UserThread(socket);
userThread.start();
}
}
} catch (IOException ex) {
System.out.println("The serverSocket stopping");
}
}
}
public static final int DEFFAULT_PORT = 8888;
private ServerSocket serverSocket;
private int port =DEFFAULT_PORT ; // 我不懂你为何不这样写呢?非得跟自己过不去。
怎么跳过呢?用socket.setSoTimeout(3000); 好像不管用了
第二个问题:线程停止的问题,建议你最好使用线程池,关闭线程池时,系统有提供函数,第一步阻塞添加新的线程,第二步等待所有线程执行完成。所以,有了线程池后,你的线程就会安全一点。
2、设置超时,server.setSoTimeout(3000); 这样server.accept 会3秒钟返回,而不是一直阻塞。
3、在想关闭server的时候设置 runServer=false/**
* 启动socket服务
*/
private void startSocketServer() {
runServer = true;
new Thread() {
public void run(){
startSocketServer(SERVERPORT);
beginServerSocketListen();
}
}.start();
}/**
* 开启监听,循环接受客户端发送的消息
*/
public void beginServerSocketListen() {
System.out.println(" controlPlayerUIApplication socket Server is Running ....");
while (runServer) {
System.out.println("beginServerSocketListen-------running=="+runServer);
Socket socket = null;
try {
server.setSoTimeout(3000);
socket = server.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); String receiveMSG = in.readLine();
System.out.println(" ControlPlayerUIApplication RECEIVE MESSAGE:|" + receiveMSG + "|---------");
in.close();
} catch (IOException e) {
//e.printStackTrace();
} finally {
try {
if(socket != null) {
socket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}