[Java TCP/IP Soket]― 剖析TCP中的死锁(二)

2014-11-24 07:43:04 · 作者: · 浏览: 6
缓冲区比较小,不会造成客户端中RecvQ队列被填满 , 相应的服务端中RecvQ队列也不会被填满;

坏处:客户端中得使用不同的线程,分别进行write() 和 read( )操作;

/*
 * 服务端
 */
public class TestServer
{
    public static void main(String[] args) throws IOException
    {
        System.out.println("服务端启动......");
        ServerSocket server = new ServerSocket(8888);

        Socket client = server.accept();
        OutputStream output = client.getOutputStream();
        InputStream input = client.getInputStream();

        byte[] temp = new byte[10];
        int realLen = 0;
        while ((realLen = input.read(temp)) != -1)
        {
            System.out.println("【服务端】正在发送数据......");
            output.write(temp, 0, realLen);
        }
        System.out.println("【客户端】发送数据完毕!");
        output.flush();

        client.close();
    }
}

/*
 * 客户端
 */
public class TestClient
{
    public static void main(String[] args) throws UnknownHostException,
            IOException
    {
        System.out.println("客户端启动......");
        final Socket client = new Socket(InetAddress.getLocalHost(), 8888);

        final OutputStream out = client.getOutputStream();
        InputStream in = client.getInputStream();
        final FileInputStream fileIn = new FileInputStream(new File(
                "D:\\杂乱\\桌面.jpg"));

        // 使用一个子线程发送数据
        Thread handlerExecute = new Thread()
        {
            @Override
            public void run()
            {
                try
                {
                    byte[] fileTemp = new byte[1024];
                    int realFileLen = 0;

                    while ((realFileLen = fileIn.read(fileTemp)) != -1)
                    {
                        System.out.println("【客户端】正在发送数据......");
                        out.write(fileTemp, 0, realFileLen);
                    }
                    System.out.println("【客户端】发送数据完毕!");

                    out.flush();
                    client.shutdownOutput();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        };

        handlerExecute.start();

        // 使用主线程接收数据
        ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
        int realLen = 0;
        byte[] temp = new byte[10];
        // 服务端采用边读边写的方式
        while ((realLen = in.read(temp)) != -1)
        {
            byteArray.write(temp, 0, realLen);
        }
        byte[] recvByte = byteArray.toByteArray();

        System.out.println("客户端接收消息成功,消息长度:" + recvByte.length);

    }
}

方案二: 服务端不采用 “边读边写” 的方式,而是采用 “全部读完在全部发送” 的方式

好处:这样,服务端和客户端的RecvQ队列就不会出现被填满的情况;

坏处:不适用于大文件的传输,这样创建的缓冲区会比较大,很可能会造成数据的丢失;

/*
 * 服务端
 */
public class TestServer
{
    public static void main(String[] args) throws IOException
    {
        System.out.println("服务端启动......");
        ServerSocket server = new ServerSocket(8888);

        Socket client = server.accept();
        OutputStream output = client.getOutputStream();
        InputStream input = client.getInputStream();

        ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
        byte[] temp = new byte[10];
        int realLen = 0;
        while ((realLen = input.read(temp)) != -1)
        {
            byteArray.write(temp, 0, realLen);
        }

        byte[] recvByte = byteArray.toByteArray();

        System.out.println("【服务端】正在发送数据......");
        output.write(recvByte);
        output.flush();
        System.out.println("【客户端】发送数据完毕!");

        client.close();
    }
}

/*
 * 客户端
 */
public class TestClient
{
    public static void main(String[] args) throws UnknownHostException,
            IOException
    {
        System.out.println("客户端启动......");
        final Socket client = new Socket(InetAddress.getLocalHost(), 8888);

        final OutputStream out = client.getOutputStream();
        InputStream in = client.getInputStream();
        final FileInputStream fileIn = new FileInputStream(new File(
                "D:\\杂乱\\桌面.jpg"));

        byte[] fileTemp = new byte[1024];
        int realFileLen = 0;