socket死锁~~请大家帮忙看看~在线等~服务器端可以接收到数据并处理,但是不能向客户端返回


//客户端
public class ClientTest_Short {   
    private ClientSocket_Short cs = null;   
  
    private String ip = "localhost";// 设置成服务器IP   
  
    private int port = 8821;   
  
    private String sendMessage = "sss"; 
    
    private Socket socket = null;
  
    public ClientTest_Short() {   
        try {   
            if (createConnection()) {   
                sendMessage();   
//                getMessage();   
            }   
  
        } catch (Exception ex) {   
            ex.printStackTrace();   
        }   
    }   
  
    private boolean createConnection() {   
        cs = new ClientSocket_Short(ip, port);   
        try {   
            socket = cs.CreateConnection();   
            if(socket != null)
            {
             System.out.print("连接服务器成功!" + "\n");   
            }
            else
            {
             System.out.println("socket is null");
            }
            return true;   
        } catch (Exception e) {   
            System.out.print("连接服务器失败!" + "\n");   
            return false;   
        }   
  
    }   
  
    private void sendMessage() throws IOException {   
        String filePath = "D:\\OOo_3.2.0rc5_20100203_Win32Intel_install_wJRE_zh-CN.exe";   
        File fi = new File(filePath);   

        System.out.println("文件长度:" + (int) fi.length());      
        System.out.println("建立socket链接");

        DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));   
        DataOutputStream ps = new DataOutputStream(socket.getOutputStream());   
        //将文件名及长度传给客户端。这里要真正适用所有平台,例如中文名的处理,还需要加工,具体可以参见Think In Java 4th里有现成的代码。   
        ps.writeUTF(fi.getName());
        ps.flush();   
        ps.writeLong((long) fi.length());   
        ps.flush();   

        int bufferSize = 8192;   
        byte[] buf = new byte[bufferSize];   

        while (true) {   
            int read = 0;   
            if (fis != null) {   
                read = fis.read(buf);   
            }   

            if (read == -1) {   
                break;   
            }   
            ps.write(buf, 0, read);   
        }   
        ps.flush();                   
        fis.close(); 
        
        //接收服务器端成功返回信息
        DataInputStream inputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
        //在这里发生死锁或者阻塞
        System.out.println("从服务器返回的信息 = " + inputStream.readUTF());
        
        socket.close();                   
        System.out.println("文件传输完成");                
    }   


    public static void main(String arg[]) {   
        new ClientTest_Short();   
    }   
}  

//服务器端
public class ServerTest_Short {   
    int port = 8821;   
  
    void start() {   
        Socket s = null;   
        try {   
            ServerSocket ss = new ServerSocket(port);   
            while (true) {   
                // 选择进行传输的文件   
                String filePath = "D:/compress-image.sh";   
                File fi = new File(filePath);   
  
                System.out.println("文件长度:" + (int) fi.length());   
  
                // public Socket accept() throws   
                // IOException侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞。   
  
                s = ss.accept();   
                DataInputStream inputStream = null;   
                try {   
                    inputStream = new DataInputStream(new BufferedInputStream(s.getInputStream())); 
                } catch (Exception e) {   
                    System.out.print("接收消息缓存错误\n");   
                    return;   
                }   
          
                try {   
                    //本地保存路径,文件名会自动从服务器端继承而来。   
                    String savePath = "E:\\";   
                    int bufferSize = 8192;   
                    byte[] buf = new byte[bufferSize];   
                    int passedlen = 0;   
                    long len=0;   
                       
                    savePath += inputStream.readUTF();
                    System.out.println("savePath = " + savePath);
                    DataOutputStream fileOut = new DataOutputStream(new BufferedOutputStream(new BufferedOutputStream(new FileOutputStream(savePath))));   
                    len = inputStream.readLong();   
                       
                    System.out.println("文件的长度为:" + len + "\n");   
                    System.out.println("开始接收文件!" + "\n");   
                               
                    while (true) {   
                        int read = 0;   
                        if (inputStream != null) {   
                            read = inputStream.read(buf);   
                        }   
                        passedlen += read;   
                        if (read == -1) {   
                            break;   
                        }   
                        //下面进度条本为图形界面的prograssBar做的,这里如果是打文件,可能会重复打印出一些相同的百分比   
//                        System.out.println("文件接收了" +  (passedlen * 100/ len) + "%\n");   
                        fileOut.write(buf, 0, read);   
                    }   
                    System.out.println("接收完成,文件存为" + savePath + "\n");   
                    fileOut.close();   
                    
                    //将成功信息返回客户端
                    DataOutputStream outputStream = new DataOutputStream(s.getOutputStream());
                    outputStream.writeUTF("success");
                    outputStream.flush();
                    
                } catch (Exception e) {   
                    System.out.println("接收消息错误" + "\n");   
                    return;   
                }         

            }   
  
        } catch (Exception e) {   
            e.printStackTrace();   
        }   
    }   
  
    public static void main(String arg[]) {   
        new ServerTest_Short().start();   
    }  
}

//工具类
public class ClientSocket_Short {   
    private String ip;   
  
    private int port;   
  
    private Socket socket = null;   
  
    DataOutputStream out = null;   
  
    DataInputStream getMessageStream = null;   
  
    public ClientSocket_Short(String ip, int port) {   
        this.ip = ip;   
        this.port = port;   
    }   
  
    /** *//**  
     * 创建socket连接  
     *   
     * @throws Exception  
     *             exception  
     */  
    public Socket CreateConnection() throws Exception {   
        try {   
            socket = new Socket(ip, port);   
        } catch (Exception e) {   
            e.printStackTrace();   
            if (socket != null)   
                socket.close();   
            throw e;   
        } finally {   
        }
        return socket;
    }   
  
    public void sendMessage(String sendMessage) throws Exception {   
        try {   
            out = new DataOutputStream(socket.getOutputStream());   
            if (sendMessage.equals("Windows")) {   
                out.writeByte(0x1);   
                out.flush();   
                return;   
            }   
            if (sendMessage.equals("Unix")) {   
                out.writeByte(0x2);   
                out.flush();   
                return;   
            }   
            if (sendMessage.equals("Linux")) {   
                out.writeByte(0x3);   
                out.flush();   
            } else {   
                out.writeUTF(sendMessage);   
                out.flush();   
            }   
        } catch (Exception e) {   
            e.printStackTrace();   
            if (out != null)   
                out.close();   
            throw e;   
        } finally {   
        }   
        System.out.println("发送结束1");
    }   
  
    public DataInputStream getMessageStream() throws Exception {   
        try {   
            getMessageStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));   
            return getMessageStream;   
        } catch (Exception e) {   
            e.printStackTrace();   
            if (getMessageStream != null)   
                getMessageStream.close();   
            throw e;   
        } finally {   
        }   
    }   
  
    public void shutDownConnection() {   
        try {   
            if (out != null)   
                out.close();   
            if (getMessageStream != null)   
                getMessageStream.close();   
            if (socket != null)   
                socket.close();   
        } catch (Exception e) {   
  
        }   
    }   
}  

5 个解决方案

#1


不解,帮顶以下吧...

#2


我也遇到同样的问题,亟待高手出现啊!

#3


代码太多了,给你个例子看看。
服务器端:

package com;

import java.awt.FileDialog;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class Server extends JFrame {
private Socket socket;
private DataInputStream input;
private DataOutputStream output;

public Server() {
try {
ServerSocket s = new ServerSocket(8007);
socket = s.accept();

FileDialog d = new FileDialog(this, "选择发送文件", FileDialog.LOAD);
d.setVisible(true);

File file = new File(d.getDirectory() + d.getFile());

output = new DataOutputStream(socket.getOutputStream());
input = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
output.writeUTF(file.getName());
output.flush();
output.writeLong((long) file.length());
output.flush();

int size = 1024000;
byte[] buf = new byte[size];
while(true){
int read = 0;
if(input != null){
read = input.read(buf);
}

if(read == -1){
break;
}
output.write(buf, 0, read);
}
output.flush();
output.close();
input.close();
socket.close();
JOptionPane.showMessageDialog(null, "发送完毕!");
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
new Server();
}
}

客户端:
package com;

import java.awt.FlowLayout;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;

public class Client extends JFrame{
private Socket socket;
private DataInputStream input;
private DataOutputStream output;
private JLabel lab;
private JProgressBar bar;
public Client(){
super("正在接收文件");
this.setLayout(null);

lab = new JLabel("文件长度:");
lab.setBounds(5, 10, 150, 30);
JLabel hasOver = new JLabel("已完成");
hasOver.setBounds(5, 40, 150, 20);

bar = new JProgressBar();
bar.setBounds(5, 80, 180, 10);
bar.setMaximum(100);
bar.setValue(0);

this.add(lab);
this.add(hasOver);
this.add(bar);

this.setBounds(130, 90, 200, 400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
getFile();
}

public void getFile(){
try {
socket = new Socket("127.0.0.1", 8007);
input = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
JOptionPane.showMessageDialog(null, "开始接收文件");
String path = "E:\\";
int size = 1024000;
byte[] buf = new byte[size];
int passlen = 0;
long len = 0;

path += input.readUTF();

DataOutputStream fileout = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
len = input.readLong();
lab.setText(lab.getText()+len);
while(true){
int read = 0;
if(input != null){
read = input.read(buf);
}
passlen += read;
if(read == -1){
break;
}
fileout.write(buf, 0, read);
bar.setValue((int)((double)passlen/len * 100));
}
fileout.flush();
fileout.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
JOptionPane.showMessageDialog(null, "文件接收完毕!");
System.exit(0);
}
public static void main(String[] args) {
new Client();
}
}

#4


代码整好了再上传撒,看得累。
找到楼主的问题所在了,分析如下发送端代码:

int bufferSize = 8192;  
byte[] buf = new byte[bufferSize];  

while (true) {  
int read = 0;  
read = fis.read(buf);  
if (-1 == read) {  // 读取文件至结尾,条件判断没问题
break;  
}  
ps.write(buf, 0, read);  
ps.flush();  // 写好之后刷新下
}  
fis.close(); 

看接收端代码:

while (true) {  
int read = 0;  
read = inputStream.read(buf);  
passedlen += read;  
if (read == -1) {  // 这个条件判断有问题!
break;  
}  
//下面进度条本为图形界面的prograssBar做的,这里如果是打文件,可能会重复打印出一些相同的百分比  
// System.out.println("文件接收了" + (passedlen * 100/ len) + "%\n");  
fileOut.write(buf, 0, read);  
fileOut.flush();
}  

思维误区:这里客户端往服务器端传送文件,客户端的确是将文件都读取了然后通过socket
发送给服务器,然后服务器只管接收就行了,反正最后客户端发送完成之后我们的服务器端
的read就会返回-1,从而终止循环,程序继续往下。
分析:反问一句,你怎么就知道服务器端的read就一定会返回-1呢,查看jdk就会知道:
read是在读到文件/流结尾而没有字节可用时才会返回-1,而我们的客户端并没有发送
一个“凭证”说它已经发完了啊,所以服务器端就会一直阻塞在read上面,它还
“以为”是由于网络问题而网速慢呢,呵呵。
怎么解决:换个思路,在客户端发送文件时先发送这个文件的长度(程序中有做),然后服务器
端获得这个长度,然后客户端只管将文件读出来并开始发送,服务器端记录已接收到的字节数,
一接收到指定长度的字节数后就可以退出循环了,所以,以上程序只要改一个地方就可正常工作了:

// len为应该接收的字节,read为每次接收到的字节
// 应该接收的字节数减去已经接收到的字节数为0时就可以退出循环了
if (0 == (len -= read)) {  
    break;  
}  

Outpu:
客户端:
连接服务器成功!
文件长度:9098566
建立socket链接
从服务器返回的信息 = success
文件传输完成

服务器端:
文件长度: 603
savePath = ./xxxAllRise.mp3
文件的长度为:9098566

开始接收文件!

接收完成,文件存为./xxxAllRise.mp3

文件长度: 603
^C

#5


kankan111111
智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告