Java 套接字程序中的线程面临死锁
我正在开发一个程序,用户可以在其中下载许多文件。现在,我首先将文件列表发送给用户。因此,用户从列表中一次选择一个文件,并提供存储该文件的路径。反过来,它还为服务器提供文件所在的路径 我之所以采用这种方法,是因为我希望提供类似流的体验,而不受文件大小限制 这是我的密码 1) 这是每次启动应用程序时启动的服务器Java 套接字程序中的线程面临死锁,java,multithreading,sockets,Java,Multithreading,Sockets,我正在开发一个程序,用户可以在其中下载许多文件。现在,我首先将文件列表发送给用户。因此,用户从列表中一次选择一个文件,并提供存储该文件的路径。反过来,它还为服务器提供文件所在的路径 我之所以采用这种方法,是因为我希望提供类似流的体验,而不受文件大小限制 这是我的密码 1) 这是每次启动应用程序时启动的服务器 public class FileServer extends Thread { private ServerSocket socket = null; public F
public class FileServer extends Thread {
private ServerSocket socket = null;
public FileServer() {
try {
socket = new ServerSocket(Utils.tcp_port);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
try {
System.out.println("request received");
new FileThread(socket.accept()).start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
2) 该线程分别为每个客户端运行,并将请求的文件一次发送给用户8kb的数据
public class FileThread extends Thread {
private Socket socket;
private String filePath;
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public FileThread(Socket socket) {
this.socket = socket;
System.out.println("server thread" + this.socket.isConnected());
//this.filePath = filePath;
}
@Override
public void run() {
// TODO Auto-generated method stub
try
{
ObjectInputStream ois=new ObjectInputStream(socket.getInputStream());
try {
//************NOTE
filePath=(String) ois.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
File f = new File(this.filePath);
byte[] buf = new byte[8192];
InputStream is = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(is);
ObjectOutputStream oos = new ObjectOutputStream(
socket.getOutputStream());
int c = 0;
while ((c = bis.read(buf, 0, buf.length)) > 0) {
oos.write(buf, 0, c);
oos.flush();
// buf=new byte[8192];
}
oos.close();
//socket.shutdownOutput();
// client.shutdownOutput();
System.out.println("stop");
// client.shutdownOutput();
ois.close();
// Thread.sleep(500);
is.close();
bis.close();
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
注意:这里filePath表示文件在服务器上的路径。连接到服务器的客户端提供此路径。我正在通过套接字管理它,并且我正在成功地接收此路径
3) FileReceiverThread负责从服务器接收数据,并从该缓冲区数据构造文件
public class FileReceiveThread extends Thread {
private String fileStorePath;
private String sourceFile;
private Socket socket = null;
public FileReceiveThread(String ip, int port, String fileStorePath,
String sourceFile) {
this.fileStorePath = fileStorePath;
this.sourceFile = sourceFile;
try {
socket = new Socket(ip, port);
System.out.println("receive file thread " + socket.isConnected());
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public void run() {
try {
ObjectOutputStream oos = new ObjectOutputStream(
socket.getOutputStream());
oos.writeObject(sourceFile);
oos.flush();
// oos.close();
File f = new File(fileStorePath);
OutputStream os = new FileOutputStream(f);
BufferedOutputStream bos = new BufferedOutputStream(os);
byte[] buf = new byte[8192];
int c = 0;
//************ NOTE
ObjectInputStream ois = new ObjectInputStream(
socket.getInputStream());
while ((c = ois.read(buf, 0, buf.length)) > 0) {
// ois.read(buf);
bos.write(buf, 0, c);
bos.flush();
// buf = new byte[8192];
}
ois.close();
oos.close();
//
os.close();
bos.close();
socket.close();
//Thread.sleep(500);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
注意:现在我面临的问题是在第一次请求文件时,程序的结果与我的预期相同。我能够在第一时间传输任何大小的文件。现在,当请求第二个文件时(例如,我已将文件a、b、c、d发送给用户,并且用户已成功接收到文件a,现在他正在请求文件b),程序将在这种情况下面临死锁。它正在等待套接字的输入流。我放置了断点并试图调试它,但它并没有第二次进入FileThread的run方法。我在这里找不出错误。基本上,我正在制作一个在局域网上工作的局域网信使。我使用SWT作为UI框架。一个更基本的问题
您只处理第一个套接字
while(true) {
new FileThread(socket.accept()).start();
}
根据Peter Lawrey的建议,我从源代码中删除了所有冗余流代码。现在更改的源代码如下,问题仍然存在 1) 文件服务器中没有更改。原来如此 2) 文件线程
public class FileThread extends Thread {
private Socket socket;
private String filePath;
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public FileThread(Socket socket) {
this.socket = socket;
System.out.println("server thread" + this.socket.isConnected());
// this.filePath = filePath;
}
@Override
public void run() {
// TODO Auto-generated method stub
try
{
OutputStream oos = socket.getOutputStream();
oos.flush();
InputStream ois = socket.getInputStream();
byte[] buf = new byte[8192];
ois.read(buf);
filePath = new String(buf);
System.out.println(filePath);
File f = new File(this.filePath);
InputStream is = new FileInputStream(f);
int c = 0;
while ((c = is.read(buf, 0, buf.length)) > 0) {
oos.write(buf, 0, c);
oos.flush();
}
oos.close();
System.out.println("stop");
ois.close();
is.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
3) FileReceiverThread
public class FileReceiveThread extends Thread {
private String fileStorePath;
private String sourceFile;
private Socket socket = null;
public FileReceiveThread(String ip, int port, String fileStorePath,
String sourceFile) {
this.fileStorePath = fileStorePath;
this.sourceFile = sourceFile;
try {
socket = new Socket(ip, port);
System.out.println("receive file thread " + socket.isConnected());
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public void run() {
try {
OutputStream oos = socket.getOutputStream();
oos.write(sourceFile.getBytes());
oos.flush();
File f = new File(fileStorePath);
OutputStream os = new FileOutputStream(f);
byte[] buf = new byte[8192];
int c = 0;
// ************ NOTE
InputStream ois = socket.getInputStream();
while ((c = ois.read(buf, 0, buf.length)) > 0) {
os.write(buf, 0, c);
os.flush();
}
ois.close();
oos.close();
os.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
我还缺少什么吗?在FileReceiveThread.run中slippery@gnat:我不明白你在说什么…你能详细说明一下吗?顺便说一句:你应该在创建ObjectInputStream之前创建并刷新ObjectOutputStream,否则会导致死锁。你应该只使用ObjectInput/OutputStream发送对象,而不是原始数据。你不应该只是打印一个异常并继续,就好像它没有发生一样。好吧,这里对于每个请求的文件,单独的线程将运行,所以我认为每个共享同一服务器的客户机将有单独的套接字。您是否想说,一旦服务器的输入/输出流被使用,它们将不可用于任何其他客户端?如果你知道这个问题,请提供任何好的教程链接。。正如你所看到的,我也错过了第一次。。)