网络编程学习----(3)TCP通讯

2018-08-28  本文已影响17人  艾剪疏

1 演示TCP的传输的客户端和服务端的互访
2 读取客户端键盘输入流,并在服务端将其转换为大写字符将其返回给客户端。
3 通过TCP通讯实现文件上传
4 TCP并发上传图片

TCP通讯过程较为简单,要经过三次握手,在这期间可以反复的接受和发送数据。

1 演示TCP的传输的客户端和服务端的互访

代码如下:

客户端:

public static void main(String[] args) {
        try {
            Socket s = new Socket("192.168.0.109",10001);//1 建立socket服务。指定要连接的主机端口
            OutputStream out = s.getOutputStream();//2 获取socket流中的输出流。将数据写到该流中。通过网络发给服务端
            out.write("hello server".getBytes());
            InputStream in = s.getInputStream();//3 获取socket中的输入流,将服务端反馈的数据获取到,并打印
            byte[] buf = new byte[1024];
            int len = in.read(buf);//阻塞式方法,接受服务端返回数据
            System.out.println(new String(buf,0,len));
            s.close();//4 关闭客户端资源
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

服务端:

  public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(10001);
            Socket s = ss.accept();//阻塞式方法,接受客户端输入数据
            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip+"......conntected");
            InputStream in = s.getInputStream();//读取客户端发送数据
            byte[] buf = new byte[1024];
            int len = in.read(buf);
            System.out.println(new String(buf,0,len));
            OutputStream out = s.getOutputStream();//接收完毕之后,从服务端返回输出语句
            out.write("hello you too client".getBytes());
            s.close();
            ss.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2 读取客户端键盘输入流,并在服务端将其转换为大写字符将其返回给客户端。

使用缓冲区Buffered

代码如下:

客户端:

  public static void main(String[] args){

        try {
            Socket s = new Socket("192.168.0.109",10001);
            BufferedReader br =
                    new BufferedReader(new InputStreamReader(System.in));
            BufferedWriter bfwOUT =
                    new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//字节流转字符流
            BufferedReader brwIN =
                    new BufferedReader(new InputStreamReader(s.getInputStream()));
            String line = null;
            while((line = br.readLine())!=null){
                if("over".equals(line)){
                    break;
                }
                bfwOUT.write(line);
                bfwOUT.newLine();
                bfwOUT.flush();
               //返回服务端返回的大写数据
                String str = brwIN.readLine();
                System.out.println(str);
            }
            br.close();
            s.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

服务端:

   public static void main(String[] args){
        try {
            ServerSocket ss = new ServerSocket(10001);
            Socket s = ss.accept();//阻塞式方法,接受客户端输入数据
            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip+"......conntected");
            BufferedReader brwIN =
                    new BufferedReader(new InputStreamReader(s.getInputStream()));
            BufferedWriter bfwOUT =
                    new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//字节流转字符流
            String line = null;
            //从客户端读取,在将其转换为大写字符
            while((line = brwIN.readLine())!=null){
                bfwOUT.write(line.toUpperCase());
                bfwOUT.newLine();
                bfwOUT.flush();
                System.out.println(line);
            }
           s.close();
            ss.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

3 通过TCP通讯实现文件上传

改变的地方仅仅是读取和输出的方式,由字符流变为了文件流。

代码如下:

客户端:

 public static void main(String[] args){
        try {
            Socket s = new Socket("192.168.0.109",10001);
            BufferedReader bufr = new BufferedReader(new FileReader("E:/test/output_res.txt"));//改变的地方
            PrintWriter out = new PrintWriter(s.getOutputStream(),true);//这种输方式会自动刷新,较二中的BufferedWriter更为方便
            String line = null;
            while((line = bufr.readLine())!=null){
                out.println(line);
            }
            s.shutdownOutput();//结束标记,告诉服务端,服务已结束,可停止
            BufferedReader bufrINT = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String str =  bufrINT.readLine();
            System.out.println(str);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

服务端:

public static void main(String[] args){
        try {
            ServerSocket ss = new ServerSocket(10001);
            Socket s = ss.accept();//阻塞式方法,接受客户端输入数据
            String ip = s.getInetAddress().getHostAddress();
           System.out.println(ip+"......conntected");
            BufferedReader buFIN = new BufferedReader(new InputStreamReader(s.getInputStream()));
            PrintWriter out = new PrintWriter(new FileWriter("E:/test/111.txt"),true);
            String line = null;
            while((line = buFIN.readLine())!=null){
                out.println(line);
            }
            PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
            pw.println("上传成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4 TCP并发上传图片

需求:实现服务器多线程上传图片。

4.1 实现单线程上传图片

思路:
1、实现单个线程的图片上传。
2、优化单线程程序。根据多线程的特点,需要将单个线程上传代码中共性的部分提取出来,多线程执行。

那么首先实现单线程图片上传程序:

客户端:

 public static void main(String args[]){
        try {
            //建立连接
            Socket s = new Socket("192.168.0.109",10002);            
            FileInputStream fis = new FileInputStream("E:\\test\\sa.jpg");
            OutputStream out = s.getOutputStream();
            byte []buf = new byte[1024];

            int len = 0;
            //读取内容
            while((len = fis.read(buf))!=-1){
                out.write(buf,0,len);//写入socket流中
            }
            //结束
            s.shutdownOutput();//结束标记
            //服务端回复
            InputStream in = s.getInputStream();
            byte []bufIn = new byte[1024];
            int num = in.read(bufIn);
            System.out.println(new String(bufIn,0,num));
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

服务端:

 public static void main(String args[]){
        try {
            //建立连接
            ServerSocket ss = new ServerSocket(10002);          
            Socket s = ss.accept();
            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip+"......conntected");
            InputStream in = s.getInputStream();
            FileOutputStream fos = new FileOutputStream("H:\\Pictures\\sa1.jpg");
            byte []buf = new byte[1024];
            int len = 0;

            while((len = in.read(buf))!=-1){
                fos.write(buf,0,len);//输出上传内容
            }
            OutputStream out = s.getOutputStream();
            out.write("上传成功".getBytes());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4.2 多线程上传图片

好了,分析单线程的图片上传程序可知:在服务端上传过程中读取上传图片部分属于共性部分代码,需要使用多线程操作。

新建PicThread类实现Runnable接口,用以支持多线程上传。

代码如下:

public class PicThread implements Runnable{
    private Socket s;
    PicThread(Socket s){
        this.s = s;
    }
    @Override
    public void run() {
        int count = 1;
        String ip = s.getInetAddress().getHostAddress();
        try {
            InputStream in = s.getInputStream();
            //小代码,实现文件时,多文件的命名
            File file = new File(ip+"("+(count)+")"+".jpg");
            //遍历,直到文件编号不冲突。
            while(file.exists()){
                file = new File(ip+"("+(count++)+")"+".jpg");
            }
            FileOutputStream fos = new FileOutputStream(file);
            byte []buf = new byte[1024];
            int len = 0;
            while((len = in.read(buf))!=-1){
                fos.write(buf,0,len);
            }
            OutputStream out = s.getOutputStream();
            out.write("上传成功".getBytes());
        } catch (Exception e) {
            throw new RuntimeException(ip+"....error");
        }
    }
}

服务端代码调整

public static void main(String args[]){
        try {
            ServerSocket ss = new ServerSocket(10002);
            //阻塞式方法,循环读取,有文件上传,便不会关闭
            while(true){
                Socket s = ss.accept();
                new Thread(new PicThread(s)).start();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

为了上传的方便,在客户端也需要做条件的维护。

public static void main(String args[]){
        try {
            File file = new File(args[0]);
            if(!(file.exists() && file.isFile())){
                return;
            }
            if(!file.getName().endsWith(".jpg")){
                return;
            }

            if(file.length()>1024*1024*5){
                return;
            }
            Socket s = new Socket("192.168.0.109",10002);
            FileInputStream fis = new FileInputStream(file);
            OutputStream out = s.getOutputStream();
            byte []buf = new byte[1024];
            int len = 0;

            while((len = fis.read(buf))!=-1){
                out.write(buf,0,len);//写入socket流中
            }
            s.shutdownOutput();//结束标记
            InputStream in = s.getInputStream();
            byte []bufIn = new byte[1024];
            int num = in.read(bufIn);
            System.out.println(new String(bufIn,0,num));
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

1 启动服务端,等待。
2 启动客户端,上传图片。
通过这段代码,即可实现多线程上传图片,即多用户并发上传图片。


END

上一篇下一篇

猜你喜欢

热点阅读