Socket简单实现数据交互及上传

  

声明:本文为原创,如需转载请说明出处:http://www.cnblogs.com/gudu1/p/7669175.html 

  首先为什么要写这个呢?因为在几个月之前我还使用Socket做一个小项目,而在今天我回想起Socket的操作细节,在我脑海里使劲挖掘Socket的痕迹,竟然丝毫没有找到,所以立即写了一个小Demo来记录一下,有些东西长时间不用肯定要忘的,人的脑容量有限,跟电脑缓存一样,不够用的时候会把那些不用的占内存的给释放掉, 就到这吧,说正题。

    Socket 和 ServerSocket 的官方API解释:

    Socket : 此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。

    ServerSocket:此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。

  套接字的实际工作由 SocketImpl 类的实例执行。应用程序通过更改创建套接字实现的套接字工厂可以配置它自身,以创建适合本地防火墙的套接字。

  在这个Demo中我使用了java.net包下的两个类:Socket 和 ServerSocket ,使用到的自定义类有3个:Service 、 Client 、ServiceThread,下面配合代码来解释一下

  ServiceThread.java ,就把它当做一个服务器处理程序就好了

import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.io.*;
public class ServiceThread implements Runnable {
    Socket s = null;
    
    public ServiceThread(Socket socket) { // ①
        super();
        this.s = socket;
    }

    @Override
    public void run() {
        String ip = s.getInetAddress().getHostName(); // ②
        System.out.println("ip:"+ip); 
        try{
            InputStream is = s.getInputStream(); // ③
            byte[] buf = new byte[1024];
            int len = 0;    
            File file = new File("D:/heheCopy.java"); // ④
            OutputStream os = new FileOutputStream(file);
            System.out.println("开始上传");
            while((len = is.read(buf)) != -1){ // ⑤
                os.write(buf,0,len);  // ⑥
            }    
            System.out.println("上传完毕");
            is.close();
            os.close();
        } catch (Exception e){
            e.printStackTrace();
        }
        
    }
}

  

   ① :类只有一个构造函数,参数是Socket对象(即一个用户),因为在服务器和客户端是通过 I/O 流来交互,所以服务器端要获取客户端的IO对象(即输入输出流)。

  ②: 获取客户端的IP地址

  ③: 获取客户端的输入流,

  ④: 创建一个File对象,并指定客户端传输过来的数据存放的位置,如果不存在该文件就自动创建

  ⑤: 开始从流中读取数据,并存放在byte数组缓冲区中,在客户端的输出流未写入之前此方法一直处于阻塞状态(即等待状态)

  ⑥: 开始写入服务器本地文件

  Client.java ,当做一个客户端

public class Client {
    public static void main(String[] args) throws Exception {
        Socket s = new Socket("127.0.0.1", 10001);  // ①
        InputStream is = new FileInputStream("D:/hehe.java"); // ②
        byte[] buf = new byte[1024];
        int len = 0;
        while((len = is.read(buf))!=-1){
            s.getOutputStream().write(buf,0,len); // ③
        }
        s.shutdownOutput(); // ④
        System.out.println("读取完毕");
        is.close();
    }
}

   ①: 创建 Socket 对象,传入要连接服务器的 IP 和 端口

  ②: 创建一个输入流对象读取要上传的文件路径

  ③: 获取 Socket 输出流对象并将读取到的数据写入输出流中

  ④: 任何以前写入的数据都将被发送,如果不调用这个方法,那么在服务器端就不会知道数据已经传输完毕,将继续调用此 Socket 输入流的 read 方法,那么此时客户端只是一个Java程序,已经执行完毕,虚拟机将释放资源,这时,此Socket已经被 close掉,程序将抛出 SocketException 异常。

  Serivce.java ,服务器

public class Service{
    public static void main(String[] args)throws Exception{
        ServerSocket ss = new ServerSocket(10001); // ①
        while(true){
            Socket s = ss.accept(); // ②
            new Thread(new ServiceThread(s)).start();  // ③
        }
    }
}

  

  ①: 创建服务器对象,指定该服务器的端口号

  ②: 获得请求连接到该服务器的客户端对象Socket

  ③: 启动服务器处理程序线程,因为程序是无限循环,所以每当一个客户端连接进来都会创建一个新的线程

   

           The End。。。。。