首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

【Java TCP阻塞有关问题.】有没有好心人帮小弟我看看为什么这段代码会阻塞啊

2013-12-19 
【Java TCP阻塞问题...在线等...】有没有好心人帮我看看为什么这段代码会阻塞啊?最近看了一本《Java TCP/IP S

【Java TCP阻塞问题...在线等...】有没有好心人帮我看看为什么这段代码会阻塞啊?
最近看了一本《Java TCP/IP Socket》书中讲解了关于Socket的一些内容,其中看到关于阻塞的内容后,有点想不明白,大家能不能帮我看看代码,为什么会出现阻塞啊?

例子中有两种情况,情况1:不会出现阻塞;情况2:会出现阻塞;

代码如下:


//客户端
public class CompressClient
{
    public static final int BUFSIZE = 256;

    public static void main(String[] args) throws IOException
    {
        InetAddress inetAddr = InetAddress.getLocalHost();
        int port = 8888;
        String fileName = "D:\\杂乱\\桌面.jpg";

        FileOutputStream fileOut = new FileOutputStream(fileName + ".gz");
        final FileInputStream fileIn = new FileInputStream(new File(fileName));

        final Socket sock = new Socket(inetAddr, port);

        // 情况一:不会出现阻塞
        // Thread thread = new Thread()
        // {
        // @Override
        // public void run()
        // {
        // try
        // {
        // sendBytes(sock, fileIn);
        // }
        // catch (IOException e)
        // {
        // e.printStackTrace();
        // }
        // }
        // };

        // thread.start();

        // 情况二:会出现阻塞
        sendBytes(sock, fileIn);

        // 接收压缩服务器信息
        InputStream sockIn = sock.getInputStream();
        int bytesRead;
        byte[] buffer = new byte[BUFSIZE];
        while ((bytesRead = sockIn.read(buffer)) != -1)
        {
            fileOut.write(buffer, 0, bytesRead);
            System.out.print("R");
        }
        System.out.println();

        fileIn.close();
        fileOut.close();
        sock.close();
    }

    private static void sendBytes(Socket socket, InputStream fileIn)
            throws IOException
    {
        OutputStream sockOut = socket.getOutputStream();
        int bytesRead = 0;
        byte[] buffer = new byte[BUFSIZE];
        while ((bytesRead = fileIn.read(buffer)) != -1)
        {
            sockOut.write(buffer, 0, bytesRead);
            System.out.print("W");
        }
        System.out.println("\nClient send data complete!");
        socket.shutdownOutput();
        System.out.println("Client is deadlock? No");
    }
}


//服务端
public class TCPEchoServerExecutor
{
    public static void main(String[] args) throws IOException
    {
        int echoServProt = 8888;

        ServerSocket servSock = new ServerSocket(echoServProt);
        Logger logger = Logger.getLogger("practical");
        Executor service = Executors.newCachedThreadPool();

        while (true)


        {
            Socket clntSock = servSock.accept();
            service.execute(new CompressProtocol(clntSock, logger));
        }
    }
}



//线程任务类
public class CompressProtocol implements Runnable
{
    public static final int BUFSIZE = 1024;

    private Socket clntSock;

    private Logger logger;

    public CompressProtocol(Socket clntSock, Logger logger)
    {
        this.clntSock = clntSock;
        this.logger = logger;
    }

    public static void handleCompressClient(Socket clntSock, Logger logger)
    {
        try
        {

            InputStream in = clntSock.getInputStream();
            GZIPOutputStream out = new GZIPOutputStream(
                    clntSock.getOutputStream());

            byte[] buffer = new byte[BUFSIZE];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1)
            {
                out.write(buffer, 0, bytesRead);
            }
            out.finish();

            logger.info("Server:" + clntSock.getRemoteSocketAddress()
                    + " finished");
        }
        catch (IOException e)
        {
            logger.log(Level.WARNING, "Exception in echo protocol", e);
        }

        try
        {
            clntSock.close();
        }
        catch (IOException e)
        {
            logger.info("Exception = " + e.getMessage());
        }

    }

    @Override
    public void run()
    {
        handleCompressClient(clntSock, logger);
    }
}


把情况二 注释掉,而使用情况一的 代码,就不会阻塞。这个是什么原理啊?大家能解释解释吗?
[解决办法]

private static void sendBytes(Socket socket, InputStream fileIn)
            throws IOException
    {
        OutputStream sockOut = socket.getOutputStream();
        int bytesRead = 0;
        byte[] buffer = new byte[BUFSIZE];
        while ((bytesRead = fileIn.read(buffer)) != -1)//这里会阻塞的,因为如果没有字节读,则阻塞
        {
            sockOut.write(buffer, 0, bytesRead);


            System.out.print("W");
        }
        System.out.println("\nClient send data complete!");
        socket.shutdownOutput();
        System.out.println("Client is deadlock? No");
    }
这段代码有问题,
[解决办法]


//不管是客户机,还是服务器程序,你这段代码只能是学习用, 要用到项目中去, 不能这么简单的写.
while ((bytesRead = in.read(buffer)) != -1)
            {
             out.write(buffer, 0, bytesRead);
}

用如下代码, 自己再完善:

try{

int pava=0;
int cava=0;
int sumb=0;
int i=0;
int c=0;
ByteArrayOutputStream buffeOut =new ByteArrayOutputStream();
byte readbuf[] = new byte[10240];
while (socket.isConnected() && !socket.isClosed()) {
i++;
pava =in.available();
if(pava>0){
while ((c = in.read(readbuf)) != -1) {
buffeOut.write(readbuf, 0, c);
sumb =sumb + c;
cava =in.available();
if(cava<=0){
Thread.sleep(100);
cava =in.available();
if(cava<=0) break;
}
}
String strin = new String(buffeOut.toByteArray(),"utf-8");
System.out.println("读取流数据内容: "+strin+","+sumb);
buffeOut.reset();
//读完后回复信息.
out.write((i+",我是服务器,已收到数据!").getBytes("utf-8"));
out.flush();
if(c == -1) break;//对方关闭了输入流.
}else{
sumb=0;
out.write((i+",我是服务器,请发送数据!").getBytes("utf-8"));
out.flush();
Thread.sleep(1000);
}
}
} catch (SocketException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("Request,NO["+requestCount+"],读取流数据完成.");
}

热点排行