socket关闭

无论是服务端还是客户端,一旦有一方调用socket.close(),都表明此次通信终止,调用close会同时关闭输入输出..
在回显例子,客户端知道接收完了数据,可以先调用close(),然后服务端再调用read将返回-1,表明服务端接收来自客户端的数据完成,然后服务端也可以调用close()
对于Http协议,客户端不知道服务端发送消息的大小,必须先由服务端关闭socket,然后客户端再关闭socket.
还有一种情况,有一方知道输出完毕,但接收还得继续,所以不能直接调用close.此时可以先调用shutdownOutput,然后接收方read返回-1,表明接收完毕,然后就可以flush所有数据出去,可以自己先关闭socket,再然后就是之前的发送方,接收到之前的接收方关闭了socket,就可以处理完数据再关闭socket。
下面是一个例子,客户端发一个文件给服务端,服务端进行压缩数据,返回给客户端,客户端再接收数据保存成另一个文件.

先看客户端

import java.io.*;
import java.net.Socket;

/* WARNING: this code can deadlock if a large file (more than a few
 * 10's of thousands of bytes) is sent.
 */

public class CompressClient {

    public static final int BUFSIZE = 256;  //读缓冲大小

    public static void main(String[] args) throws IOException {
        String filename = "1.txt";//文件名
        FileInputStream fileIn = new FileInputStream(filename);
        FileOutputStream fileOut = new FileOutputStream(filename + ".gz");
        Socket sock = new Socket("127.0.0.1", 9000);
        sendBytes(sock, fileIn);//发送未压缩消息到服务端

        //接收从服务端压缩的数据
        InputStream sockIn = sock.getInputStream();
        int bytesRead;//已读字节数
        byte[] buffer = new byte[BUFSIZE];  // Byte buffer
        while ((bytesRead = sockIn.read(buffer)) != -1) {
            fileOut.write(buffer, 0, bytesRead);
            System.out.print("R");//从流入流读数据的标志
        }
        System.out.println();//已接收完从服务端发送的压缩数据

        sock.close();//关闭socket
        fileIn.close();//关闭输入文件流
        fileOut.close();//关闭输出文件流
    }

    private static void sendBytes(Socket sock, InputStream fileIn) throws IOException {
        OutputStream sockOut = sock.getOutputStream();
        int bytesRead;//已读字节数
        byte[] buffer = new byte[BUFSIZE];//缓冲
        while ((bytesRead = fileIn.read(buffer)) != -1) {
            sockOut.write(buffer, 0, bytesRead);
            System.out.print("w"); //写到输出流的写数据标志
        }
        sock.shutdownOutput();//关闭输出
    }
}

再看服务端:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.logging.Logger;

public class TCPEchoServerExecutor {
    public static void main(String[] args) throws IOException {
        // Create a server socket to accept client connection requests
        ServerSocket servSock = new ServerSocket(9000);
        Logger logger = Logger.getLogger("practical");
        Executor service = Executors.newCachedThreadPool();  // Dispatch svc
        // Run forever, accepting and spawning threads to service each connection
        while (true) {
            Socket clntSock = servSock.accept(); // Block waiting for connection
            service.execute(new CompressProtocol(clntSock, logger));
        }
    /* NOT REACHED */
    }
}
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPOutputStream;
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) {//接收消息直到客户端关闭连接(通过返回-1表明客户端关闭连接,即在客户端调用sock.shutdownOutput())
                out.write(buffer, 0, bytesRead);
            }
            out.finish();//在关闭GZIPOutputStream之前,需刷新提交可能被压缩算法缓存的字节
            logger.info("Client " + clntSock.getRemoteSocketAddress() + " finished");
        } catch (IOException ex) {
            logger.log(Level.WARNING, "Exception in echo protocol", ex);
        }
        try {//关闭Socket
            clntSock.close();
        } catch (IOException e) {
            logger.info("Exception = " + e.getMessage());
        }
    }

    public void run() {
        handleCompressClient(this.clntSock, this.logger);
    }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值