java聊天程序在文件传输期间挂起?
我有一个java聊天服务器和客户端,工作正常。我单独做了一个服务器到客户端的文件传输程序,它也可以正常工作。但当我尝试将文件传输集成到聊天中时,文件正在传输,但在此期间,聊天程序冻结,以至于我无法在聊天框中键入任何内容,当传输结束时,一切正常。如何使它正常,像聊天和文件传输是并排进行的,没有一个受到其他的影响 我的文件传输在服务器和客户端上都有while循环,我想知道这是因为while循环,我是否应该在文件传输的服务器和客户端代码上创建线程。 我的聊天系统就像,在服务器上,用户连接,在服务器上为该用户启动线程,从用户处读取,然后将这些消息从用户发送给每个人。 在客户机上,线程用于从服务器读取消息,当用户键入消息时,它将其发送到服务器,然后服务器将消息返回给连接的每个人 我想问题出在客户端,因为我刚刚和我的朋友在互联网上测试了这个,我是服务器,用于聊天和文件传输,我的聊天框很好,我可以打字,但他的聊天客户端freezd在文件传输发生时是免费的 我不知道是哪部分代码导致了这种情况,所以一旦有人要求,我会用代码更新它 谢谢, 任何帮助都将不胜感激 [编辑--客户端上的文件传输]java聊天程序在文件传输期间挂起?,java,Java,我有一个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());
}
}
//Waiting for connection
//Sending name in bytes
//While{
send files as bytes
}
}
[编辑--这就是我将文件传输代码调用到聊天客户端的方式]
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());
}
}
//Waiting for connection
//Sending name in bytes
//While{
send files as bytes
}
[编辑--文件传输服务器代码--缓冲区大小512]
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());
}
}
//Waiting for connection
//Sending name in bytes
//While{
send files as bytes
}
[调用上述(FT服务器)代码的聊天服务器]
public void actionPerformed(ActionEvent e) {
FileSv.go();
}
我的服务器也会在我按下按钮时冻结,即使FT服务器还没有连接(我认为这有帮助)
我有一个聊天服务器和客户端,两者都有线程相互读取。我试图将我的文件传输服务器和客户端集成到现有的聊天服务器和聊天客户端中。
最初,当用户连接到聊天服务器时,它会为其启动一个线程。现在,为了向那个用户发送一个文件,我在服务器上创建了一个按钮(文件发送),在客户端创建了一个按钮(接受文件),当我点击服务器上的“文件发送”时,我的文件传输服务器代码被执行,文件传输服务器在不同的端口上等待连接(我的聊天服务器现在冻结,它有一个文本字段,现在没有响应),现在,如果与我聊天的用户非常满意,那么单击“接受文件”文件传输客户端代码将被执行。FT服务器开始发送字节,FT客户端rcvs它。当传输发生时,服务器和客户端聊天窗口都会变得无响应,并且无论我在传输期间从客户端聊天盒发送了什么,在传输后都会得到更新。
这是为了消除混乱。即使这样做没有帮助,我也会上传整个代码(太大)您正在体验使用同步操作的信号,而您需要异步操作 我的猜测是,您的应用程序或者远程通信都有一个线程。您可能没有使用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 */ }
}
然后使用某种类型的
队列
,可能是ConcurrentLinkedQueue,它接受这些类型的对象,并使用生产者/消费者。注意,您还需要在代码的接收部分派生一个单独的线程。否则,您将能够异步发送,但在接收时将被阻止(这对于消息来说可能是正常的,但对于文件来说是恼人的)。当您想要异步操作时,您正在经历使用同步操作的信号
我的猜测是,您的应用程序或者远程通信都有一个线程。您可能没有使用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 */ }
}
然后使用某种类型的
队列
,可能是ConcurrentLinkedQueue,它接受这些类型的对象,并使用生产者/消费者。注意,您还需要在代码的接收部分派生一个单独的线程。否则,您将能够异步发送,但在接收时将被阻止(这对消息来说可能没问题,但对文件来说很烦人)。好,要展开我的评论-您说当单击clientchat窗口上的按钮时,FileTransferClient端被启动,它在循环从服务器读取字节时工作。
您是否在Swing事件线程中运行文件传输代码?如果是这样,您需要将其包装在可运行对象中,确保其在while循环的迭代之间产生一些处理时间,并使用SwingUtilities调用它
如果您要在按键上启动一个单独的线程来传输文件,您仍然需要在发送循环的两个循环之间留出处理时间,或者您不需要为聊天处理线程留出任何处理时间
电子数据交换