java多线程 Socket
我的主要想法是做一个服务器 可以让两个用户之间进行消息,文件传输。为此我在客户端为每个用户开辟了两个线程 一个用于文件传输一个用于消息传输,每个线程都有一个与之对应的Socket连接 同样在服务器端也为每个与它连接的客户端开了两个线程(文件传输线程,消息线程) 用来在两个客户端之间进行消息的转发。同时我将客户端与服务器端的线程都做成了死循环 以此来不断得读取传送过来的消息和文件信息。可是当我创建了一个用户时cpu的占用率就40%左右了再开一个就100% 有点崩溃了在这样下去的话,后来的什么也做不了了?求大神们帮帮看看啊到底是哪里出了问题啊,是因为我没有将线程休眠吗?那又应该在哪里休眠呢?新手请求大家的指教
同时还有一个问题在下面代码中已经标注也请大家看看啊,小女子不胜感激。
服务器端代码
public class Server1 {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(9999);
System.out.println("服务器9999号端口在监听。。");
int a = 1;//这里的a没有任何的意义,只是为了简化代码,使第一次是消息线程连接 与之连接 第二次是文件传输线程
while (true) {
Socket s = ss.accept();
if (a == 1) {
MessageServerThread mst = new MessageServerThread(s);
mst.start();
System.out.println("服务器端传输消息线程开启" + mst.getName());
a = 2;
} else if (a == 2) {
TransportFileServerThread tfst = new TransportFileServerThread(
s);
tfst.start();
System.out.println("服务器端传输文件线程开启" + tfst.getName());
a = 1;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
客户端代码:
public class LoginFrame {
public static void main(String[] args) {
// 启动两个线程
Socket s;
try {
// 用户1
s = new Socket("127.0.0.1", 9999);
MessageClientThread mct = new MessageClientThread(s);
mct.start();
System.out.println("客户端1消息线程开启" + mct.getName());
s = new Socket("127.0.0.1", 9999);
TransportFileClientThread tfct = new TransportFileClientThread(s);
tfct.start();
System.out.println("客户端1文件传输线程开启" + tfct.getName());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户端文件传输线程代码:
public class TransportFileClientThread extends Thread {
Socket s;
public TransportFileClientThread(Socket s) {
this.s = s;
}
public void run() {
while (true) {
try {
DataInputStream dis = new DataInputStream(
new BufferedInputStream(s.getInputStream()));
//之后将文件保存在本地
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
客户端消息线程代码:
public class MessageClientThread extends Thread {
Socket s;
public MessageClientThread(Socket s) {
this.s = s;
}
public void run() {
while (true) {
try {
ObjectInputStream ois = new ObjectInputStream(
s.getInputStream());
//之后处理得到的消息
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
服务器端文件传输代码:
import java.io.*;
import java.net.*;
public class TransportFileServerThread extends Thread {
Socket s;
public TransportFileServerThread(Socket s) {
this.s = s;
}
public void run() {
while (true) {
try {
DataInputStream dis = new DataInputStream(
new BufferedInputStream(s.getInputStream()));
// 之后完成文件的转发
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream(
按照 接收端的 Socket连接进行转发)));
byte[] buf = new byte[1024];
int count;
while ((count = dis.read(buf)) != -1) {
dos.write(buf, 0, 1);
dos.flush();
}
System.out.println("文件传输完毕");这就话不知道为什么老是没有执行,那是不是说明上面的while循环没有走完啊可是并没有看出代码哪里有问题啊?而且文件也的确是转发成功了 转发后的文件也创建成功了里面也有内容 可是就是不输出这句话是哪里出了问题呢求大家的指教啊
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
服务器端消息线程代码:
public class MessageServerThread extends Thread {
Socket s;
public MessageServerThread(Socket s) {http://news.csdn.net//images/top_arrow.png
this.s = s;
}
public void run() {
while (true) {
try {
ObjectInputStream ois = new ObjectInputStream(
s.getInputStream());
System.out.println("之后将信息转发给另一个人。。");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
[解决办法]
亲,socket的while ((count = dis.read(buf)) != -1) 是不会读到-1的,会一直阻塞等待另一端发来数据的。
一般传文件的做法是 定义一个格式 比如先 文件名 文件长度 文件内容 按照这张格式发送数据的,先读到文件名和文件长度然后根据文件长度再来读取流数据。
[解决办法]
给你写了个小demo
public class Server {
public static void main(String[] args) throws Exception {
new Server().start();
}
public void start() throws Exception {
ServerSocket server = new ServerSocket(7789);
Socket client = server.accept();
System.out.println(client.getInetAddress() + "已连接");
DataInputStream dis = new DataInputStream(client.getInputStream());
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
boolean flag = false;
try {
flag = dis.readBoolean();// 读取客户端发送文件的请求
} catch (Exception e) {// 不符合标准断开连接
dos.writeChars("Illegal request");// 返回非法请求信息
dos.flush();
client.close();// 关闭连接
}
if (flag) {
dos.writeBoolean(true);// 告诉客户端可以开始传输文件了
String fileName = dis.readUTF();// 读取文件名
long fileSize = dis.readLong();// 读取文件长度
byte[] buff = new byte[4096];
int len = 0;
int count = 0;
FileOutputStream fos = new FileOutputStream("c:/data/" + fileName);
while (count < fileSize) {
len = dis.read(buff);
fos.write(buff, 0, len);
count += len;
}
fos.flush();
fos.close();
System.out.println(fileName + "传输完毕!");
dos.writeBoolean(true);
dos.flush();
client.close();
}
}
}
public class Client {
public static void main(String[] args) throws Exception {
new Client().start();
}
public void start() throws Exception {
Socket server = new Socket("localhost", 7789);
DataInputStream dis = new DataInputStream(server.getInputStream());
DataOutputStream dos = new DataOutputStream(server.getOutputStream());
dos.writeBoolean(true);// 发送传输文件请求
dos.flush();
boolean flag = false;
try {
flag = dis.readBoolean();// 读取服务端返回信息
} catch (Exception e) {// 不符合标准断开连接
dos.writeChars("Illegal message");// 返回非法请求信息
dos.flush();
server.close();// 关闭连接
}
if (flag) {
File file = new File("c:/jdk-6u43-windows-x64.exe");
FileInputStream fis = new FileInputStream(file);
dos.writeUTF(file.getName());// 发送文件名
dos.writeLong(file.length());// 发送文件大小
// 发送文件
byte[] buff = new byte[4096];
int len = -1;
while ((len = fis.read(buff)) != -1) {
dos.write(buff, 0, len);
}
dos.flush();
fis.close();
if (dis.readBoolean()) {// 等待服务器端完成
server.close();
}
}
}
}