我有一个java聊天服务器&客户机,运行良好。我分别制作了一个服务器到客户端的文件传输程序,它的工作也很好。但是当我试图将文件传输整合到聊天中时,文件就会被传输,但是在这段时间里,聊天程序就会冻结,以至于我甚至不能在聊天框中输入一个东西,当传输结束时,事情就变得正常了。如何使它正常,像聊天和文件传输是并行发生,没有受到影响的另一个?
我的文件传输在服务器和客户端上都有while循环,我想知道这是因为while循环,应该在文件传输的服务器和客户端代码上创建线程。我的聊天系统就像,在服务器上,用户连接,线程在服务器上为该用户启动,为了从用户那里读取,它将这些消息从用户发送给每个人。在客户端上,线程用于从服务器读取,当用户键入消息时,它将其发送到服务器,然后服务器将消息返回给每个连接的人。
我认为问题在客户端,因为我刚刚和我的朋友在互联网上测试了这个,我是服务器,我的聊天和文件传输,我的聊天框很好,我可以打字,但他的聊天客户端冻结的时间文件传输发生。
我不知道是哪一部分代码造成了这种情况,所以只要有人要求,我就用代码更新它。
谢谢,任何帮助都会很感激的。
编辑--客户端上的文件传输
public class FileClient{
JFrame jfr;
JTextField Jtf = new JTextField(4);
public static void main (String [] args ) {
// new FileClient().go();
}
public void go(String ip){
try{
JFrame jfr = new JFrame("File Transfer");
JPanel panel = new JPanel();
JLabel jl = new JLabel("Progress:");
jfr.getContentPane().add(BorderLayout.CENTER,panel);
panel.add(jl);
panel.add(Jtf);
Jtf.setEditable(false);
jfr.setSize(200,70);
jfr.setVisible(true);
jfr.setDefaultCloseOperation(jfr.EXIT_ON_CLOSE);
}catch(Exception e){e.printStackTrace();}
long start = System.currentTimeMillis();
int read;
int totalRead = 0;
try{
Socket sock = new Socket(ip,4243);
System.out.println("Connecting...");
InputStream is = sock.getInputStream();
BufferedInputStream bis = new BufferedInputStream(new ProgressMonitorInputStream(jfr,"reading",is));
byte [] mybytearray = new byte [512];
int buff =1024;
byte[] nameByte = new byte [50];
byte[] nameByteSize = new byte [2];
byte[] Size = new byte [10];
byte[] SizeSize =new byte [1];
int num = is.read(nameByte,0,50);
int nameSize = is.read(nameByteSize,0,2);
int sz = is.read(Size,0,10);
int yy = is.read(SizeSize,0,1);
float w;
String Size1 = RemoveNameStuffing(new String(Size),new String(SizeSize));
int tt = Integer.parseInt(Size1);
System.out.println("tt"+tt);
name"+new String(nameByte));
String name = RemoveNameStuffing(new String(nameByte),new String(nameByteSize));
File f1=new File(name);
FileOutputStream fos = new FileOutputStream(f1);
BufferedOutputStream bos = new BufferedOutputStream(fos);
while ((read = bis.read(mybytearray,0,mybytearray.length)) != -1) {
bos.write(mybytearray, 0 , read);
totalRead += read;
w=((float)totalRead/tt)*100;
System.out.println("progress:"+w+"%");
Jtf.setText(w+"%");
}
bos.flush();
long end = System.currentTimeMillis();
System.out.println(end-start);
bos.close();
sock.close();
}catch(IOException e){e.printStackTrace();}
}
public static String RemoveNameStuffing(String s, String n){
s=s.substring(0,Integer.parseInt(n));
System.out.println("s:"+s);
return s;
}}
编辑--这就是我如何调用文件传输代码到聊天客户端的方式
public class AcceptFileButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
FileCl.go(JTip.getText());
}
}编辑--文件传输服务器代码-缓冲区大小512
//Waiting for connection
//Sending name in bytes
//While{
send files as bytes
}上面的聊天服务器(FT服务器)代码称为
public void actionPerformed(ActionEvent e) {
FileSv.go();
}而且我的服务器也会在我按下按钮后立即冻结,即使FT服务器还没有连接(我认为这是个帮助)。
我有一个聊天服务器和客户端,两个线程可以相互读取。我试图将我的文件传输服务器和客户端集成到现有的聊天服务器和聊天客户端中。最初,当用户连接到聊天服务器时,它会为它启动一个线程。现在,为了将文件发送给该用户,我在服务器(文件发送)上创建了一个按钮,在客户机(接受文件)上创建了一个按钮,现在当我单击服务器上的“文件发送”时,我的文件传输服务器代码被执行,文件传输服务器在不同端口上等待连接(我的聊天服务器现在冻结了,它有一个textField,现在它没有响应),现在如果我正在与其聊天的用户完美地聊天,点击"accept file“文件传输客户端代码就会被执行。FT服务器开始发送字节,FT客户端rcvs它。当时间转移发生时,服务器和客户端聊天窗口都会变得没有响应,传输期间我从客户端聊天框发送的任何内容都会在传输后更新。这是为了消除混乱。即使这不起作用,我也会上传整个代码(太大了)
发布于 2012-01-16 15:29:27
好的,扩展我的评论-你说when clicked on a button on the clientchat window, FileTransferClient side is initiated, which works on while loop to read byte from server.
在Swing事件线程中运行文件传输代码吗?如果是这样的话,您需要将它封装在一个Runnable对象中,确保它在while循环的迭代之间产生一定的处理时间,并使用SwingUtilities调用它。
如果要在按钮上启动单独的线程以传输文件,则仍然需要在发送循环的循环之间腾出处理时间,否则就不会给聊天处理线程带来任何处理时间。
编辑:修改您的动作侦听器调用,以执行以下操作:
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
FileCl.go(JTip.getText());
}
}
);
}这样做是将文件下载的CPU和IO密集型处理移到Swing事件线程外部的新线程中。
发布于 2012-01-16 15:28:44
当您想要异步操作时,您正在经历使用同步操作的告警信号。
我的猜测是,您的应用程序有一个线程,或者远程通信有一个线程。您可能不会将java的nio类用于异步通信。
您可以查看nio类,也可以在单独的线程中执行当前的文件发送和文件接收代码。
前者的实现可以在一个不错的nio教程中找到(以下是一)。
后者的一个常见实现是使用命令模式发送消息/文件,并使用带有生产者/使用者线程的命令队列。您可以将"Runnable“接口视为命令类。
public class MessageCommand implements Runnable {
private String message;
public MessageCommand(String message) { this.message = message; }
public void run() { /* code to send the message goes here */ }
}
public class FileCommand implements Runnable {
private File file; /* or byte[] or whatever */
public MessageCommand(File file) { this.file = file; }
public void run() { /* code to send the file goes here */ }
}然后拥有某种类型的Queue<Runnable>,可能是ConcurrentLinkedQueue,它接受这些类型的对象,并使用生产者/使用者。请注意,您还需要在代码的接收部分分离一个单独的线程。否则,您将能够异步发送,但在接收时会阻塞(这对于消息来说可能是可以的,但对于文件则是烦人的)。
https://stackoverflow.com/questions/8881836
复制相似问题