java socket 问题,{高手}请进! 不久后服务器和客户会死掉 ,是因为,所以的客户都卡在了 in.readLine() 上 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 1:userList.add(client);运行时还不能保证client.out被初始化。应该把这条语句放在client线程里out被初始化后2:多线程的资源访问同步。涉及userlist的操作、broadcast都需要线程同步。你对synchronized的使用方法还没有理解。在run上和sendToChat上使用的synchronized都是不正确的,不能起到你想要的效果。3:客户端收到的消息数要比发送的消息数要多得多,你在同一个线程里发一次收一次,显然是不正确的。这个题目确实是多线程程序的典型例子,你改好了再贴上了。 首先感谢[taolei(实在无聊) ]的敬业精神,你是真心为我解答的,看清了程序中的许多问题,万分感谢,凭着这种精神和心细密,一定是大有前途的!按照你所说程序确实有了质的改观,但有人建议我做成双线程,一个线程管收控制out,一个管发控制in,不知你对此有什么看法?下面是我改好的程序,可能还是不尽如人意的地方,但已经可以用了。server.javaimport java.net.*;import java.util.*;import java.io.*;public class Server extends Thread{ private ServerSocket server; private Socket socket; private boolean isRun; private LinkedList userList; public Server(int port) { this.userList=new LinkedList(); try { server = new ServerSocket(port); } catch (IOException ex) { System.out.println("-1:"+ex); } } public void run(){ int i = 0; isRun = true; while (isRun) { try { this.socket = server.accept(); } catch (IOException ex) { System.out.println("---1:"+ex); } CliThread client = new CliThread(userList, socket); client.start(); client.setName("_user" + i); System.out.println(i+"---------------------------"+client.getName()+" success!"); i++; } } public static void main(String args[]) { Server aa = new Server(3001); aa.start(); }}CliThread.java/** * <p>Title: </p> * * <p>Description: </p> * * <p>Copyright: Copyright (c) 2004</p> * * <p>Company: </p> * * @author not attributable * @version 1.0 */import java.io.*;import java.net.*;import java.util.*;public class CliThread extends Thread{ private BufferedReader in; private PrintWriter out; private Socket socket; private LinkedList userList; public CliThread(LinkedList userList,Socket socket) { this.userList=userList; this.socket=socket; } public void run(){ try { in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out=new PrintWriter(socket.getOutputStream()); synchronized(userList){ userList.add(out); } String data=null; int i=0; while((data=in.readLine())!=null){ System.out.println(i+"---------------"+data); broadcast(data); i++; } } catch (IOException ex) { System.out.println("2:"+ex); } } public void send(String msg){ out.println(msg); out.flush(); } public synchronized void broadcast(String msg){ for(int j=0;j<userList.size();j++){ PrintWriter client=(PrintWriter)userList.get(j); out.println(msg); out.flush(); } }}Client.java/** * <p>Title: </p> * * <p>Description: </p> * * <p>Copyright: Copyright (c) 2004</p> * * <p>Company: </p> * * @author not attributable * @version 1.0 */import java.net.*;import java.io.*;import java.sql.*;public class Client extends Thread { private boolean running; private PrintWriter out; private BufferedReader in; private Socket socket; private String server = "localhost"; private int port; private String name; public Client(String name,int port) { this.name=name; this.port=port; connect(); } public void run() { char charBuffer[] = new char[1]; sendToChat("<login CN='"+this.name+"' x='111' y='-34' />"); running = true; while (running) { int ran=(int)(Math.round(Math.random()*6)+1); int x=(int)(Math.round(Math.random()*500)); int y=(int)(Math.round(Math.random()*120)); switch(ran){ case 1:sendToChat("<face ID='"+this.name+"' value='3' />");break; case 2:sendToChat("<face ID='"+this.name+"' value='3' />");break; case 3:sendToChat("<face ID='"+this.name+"' value='3' />");break; case 4:sendToChat("<face ID='"+this.name+"' value='3' />");break; case 5:sendToChat("<face ID='"+this.name+"' value='3' />");break; case 6:sendToChat("<face ID='"+this.name+"' value='3' />");break; default:sendToChat("<face ID='"+this.name+"' value='3' />"); } try { while(in.ready()){ System.out.println(in.readLine()); } this.sleep(20); } catch (Exception ex) { System.out.println(ex); } } } private int connect() { try { socket = new Socket(server, port); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(socket.getOutputStream()); } catch (UnknownHostException ex) { return 1; } catch (IOException ex) { return 2; } return 0; } public synchronized void sendToChat(String msg) { out.println(msg); //out.write(msg); out.flush(); } private void shutdown() throws IOException { in.close(); out.close(); socket.close(); } public static void main(String args[]) { int limit=40; for(int i=0;i<limit;i++){ Client cc=new Client("aabbcc"+i,Integer.parseInt(args[0])); cc.start(); try { Thread.sleep(500); } catch (InterruptedException ex) { } } System.out.println("---------------------finish!"); }} server端还有点问题:前面用的synchronized(userlist),那么broadcast也应该用synchronized(userlist)当一个客户端连接断开后,server端并没有把这个连接从userlist里删除,同时你的broadcast里并未catch任何异常,所有其他的连接同时也会收到影响。我也是建议客户端用两个线程,一个发送,一个接收。 如果是多个客户,就应用多线程,否则到readLine()时程序会等待,他也就不会处理其它用户的工作,相当于死了。 请教下GET和POST方法发送请求action里获取参数的区别 继续问个简单的查询知识点问题,哥哥们。 请教字符串转义 帮忙解决一下下 添加spring3支持时,出错 struts2问题 Struts+Hibernate+Spring搭建的平台问题? 新手求帮忙解决下数据库连接不上问题 hibernate中什么方法能返回查询到的结果数量? 新手问题 高分求救 下载源文件 请教用JAVA编写简单的分析器的步骤及例子?
2:多线程的资源访问同步。涉及userlist的操作、broadcast都需要线程同步。你对synchronized的使用方法还没有理解。在run上和sendToChat上使用的synchronized都是不正确的,不能起到你想要的效果。3:客户端收到的消息数要比发送的消息数要多得多,你在同一个线程里发一次收一次,显然是不正确的。这个题目确实是多线程程序的典型例子,你改好了再贴上了。
按照你所说程序确实有了质的改观,但有人建议我做成双线程,一个线程管收控制out,一个管发控制in,不知你对此有什么看法?下面是我改好的程序,可能还是不尽如人意的地方,但已经可以用了。server.java
import java.net.*;
import java.util.*;
import java.io.*;
public class Server extends Thread{
private ServerSocket server;
private Socket socket;
private boolean isRun;
private LinkedList userList; public Server(int port) {
this.userList=new LinkedList();
try {
server = new ServerSocket(port); } catch (IOException ex) {
System.out.println("-1:"+ex);
}
} public void run(){
int i = 0;
isRun = true;
while (isRun) {
try {
this.socket = server.accept();
} catch (IOException ex) {
System.out.println("---1:"+ex);
}
CliThread client = new CliThread(userList, socket);
client.start();
client.setName("_user" + i);
System.out.println(i+"---------------------------"+client.getName()+" success!");
i++;
} }
public static void main(String args[]) {
Server aa = new Server(3001);
aa.start();
}
}
CliThread.java/**
* <p>Title: </p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2004</p>
*
* <p>Company: </p>
*
* @author not attributable
* @version 1.0
*/import java.io.*;
import java.net.*;
import java.util.*;public class CliThread extends Thread{
private BufferedReader in;
private PrintWriter out;
private Socket socket;
private LinkedList userList; public CliThread(LinkedList userList,Socket socket) {
this.userList=userList;
this.socket=socket;
} public void run(){
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out=new PrintWriter(socket.getOutputStream());
synchronized(userList){
userList.add(out);
}
String data=null;
int i=0;
while((data=in.readLine())!=null){
System.out.println(i+"---------------"+data);
broadcast(data);
i++;
}
} catch (IOException ex) {
System.out.println("2:"+ex);
}
}
public void send(String msg){
out.println(msg);
out.flush();
}
public synchronized void broadcast(String msg){
for(int j=0;j<userList.size();j++){
PrintWriter client=(PrintWriter)userList.get(j);
out.println(msg);
out.flush();
}
}
}Client.java
/**
* <p>Title: </p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2004</p>
*
* <p>Company: </p>
*
* @author not attributable
* @version 1.0
*/import java.net.*;
import java.io.*;
import java.sql.*;public class Client extends Thread {
private boolean running;
private PrintWriter out;
private BufferedReader in;
private Socket socket;
private String server = "localhost";
private int port;
private String name; public Client(String name,int port) {
this.name=name;
this.port=port;
connect();
} public void run() { char charBuffer[] = new char[1];
sendToChat("<login CN='"+this.name+"' x='111' y='-34' />");
running = true; while (running) {
int ran=(int)(Math.round(Math.random()*6)+1);
int x=(int)(Math.round(Math.random()*500));
int y=(int)(Math.round(Math.random()*120));
switch(ran){
case 1:sendToChat("<face ID='"+this.name+"' value='3' />");break;
case 2:sendToChat("<face ID='"+this.name+"' value='3' />");break;
case 3:sendToChat("<face ID='"+this.name+"' value='3' />");break;
case 4:sendToChat("<face ID='"+this.name+"' value='3' />");break;
case 5:sendToChat("<face ID='"+this.name+"' value='3' />");break;
case 6:sendToChat("<face ID='"+this.name+"' value='3' />");break;
default:sendToChat("<face ID='"+this.name+"' value='3' />");
}
try {
while(in.ready()){
System.out.println(in.readLine());
}
this.sleep(20);
}
catch (Exception ex) {
System.out.println(ex);
}
}
}
private int connect() {
try {
socket = new Socket(server, port);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream()); }
catch (UnknownHostException ex) {
return 1;
}
catch (IOException ex) {
return 2;
}
return 0;
} public synchronized void sendToChat(String msg) {
out.println(msg); //out.write(msg);
out.flush(); } private void shutdown() throws IOException {
in.close();
out.close();
socket.close();
} public static void main(String args[]) { int limit=40;
for(int i=0;i<limit;i++){
Client cc=new Client("aabbcc"+i,Integer.parseInt(args[0]));
cc.start();
try {
Thread.sleep(500);
}
catch (InterruptedException ex) {
}
}
System.out.println("---------------------finish!");
}
}
前面用的synchronized(userlist),那么broadcast也应该用synchronized(userlist)当一个客户端连接断开后,server端并没有把这个连接从userlist里删除,同时你的broadcast里并未catch任何异常,所有其他的连接同时也会收到影响。我也是建议客户端用两个线程,一个发送,一个接收。