网络编程(一)

2020-07-20  本文已影响0人  Responsibility_

TCP协议与UDP协议是运输层的两个重要的协议,通过这两个协议来进行两台计算机通信.

套接字

soket是网络驱动层提供应用层的编程的接口和一种数据发送、接受机制,告诉网络驱动层当前应用程序所对应的IP地址和端口号

TCP通信模型

image.png

ServerSocket作为服务器端(绑定端口号),监听客户端访问,每一个客户端建立对应Socket

//创建服务器对象
ServerSocket serversocket = new ServerSocket(6010);
//监听客户端访问
Socket socket = serversocket.accept();

Socket作为客户端(IP地址+端口号)

//创建客户端对象
socket = new Socket("192.168.104.163", 6006);

TCPSocket通信过程

TCP通信过程.png

客户端,通过Socket对象创建输出字节流

OutputStream outputstream = socket.getoutputStream();
//向服务器端发送信息
            OutputStream outputStream = socket.getOutputStream();
            //输入信息字节
            outputStream.write("我是刘德华".getBytes());
            //刷新缓存区域
            outputStream.flush();

服务器端,通过Socket对象创建输入字节流

            //获取客户端信息,输入流,读入    
            InputStream inputStream =socket.getInputStream();
            byte[] b = new byte[1024];
            //读取信息
            int length = inputStream.read(b);
            //字节信息转换为String
            String str = new String(b,0,length)

代码示例

以图片文件上传为例,结合多线程操作.
服务器代码

package com.apesource.demo;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
* 服务器端最重要的是端口号,监听端口有没有客户端来访问,保存来自客户端的图片
*/
public class ServiceImgetTest {

   public static void main(String[] args) {
       try(ServerSocket serverSocket = new ServerSocket(8030)) {
           // 创建服务器端
           
           System.out.println("服务器已经启动");
           // 监听客户端
           Socket socket = serverSocket.accept();
           System.out.println("客户端已经连接");
           Thread thread = new Thread(new ImageloadThread(socket));
           thread.start();
       } catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }

   }

}

//使用多线程来保存图片
class ImageloadThread implements Runnable {

   // 关联Socket
   private Socket socket;

   public ImageloadThread(Socket socket) {
       this.socket = socket;
   }

   @Override
   public void run() {
       try {
           // 创建用来保存图片的目录
           File file = new File("E:\\Image\\Test");
           // 不存在就创建文件夹
           if (!file.exists()) {
               file.mkdirs();
           }
           // 创建用来保存图片的文件
           File imageFile = new File(
                   file.getName() + File.separator + System.currentTimeMillis() + ((int) Math.random() * 10000) + ".jpg");
           // 如果文件不在就创建文件
           if (!imageFile.exists()) {
               imageFile.createNewFile();
           }
           //读取客户端发来的图片
           InputStream inputStream = socket.getInputStream();
           
           //创建字节数组
           byte[] data = new byte[1024];
           
           //创建输出流,写入本地磁盘
           BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(imageFile));
           
           //读操作
           int length = -1;
           while((length=inputStream.read(data))!= -1) {
               //边读边写入磁盘
               bos.write(data,0,length);
               bos.flush();
           }
           bos.close();
           
           //向客户端返回成功
           OutputStream outputStream = socket.getOutputStream();
           outputStream.write("成功了呢".getBytes());
       
       } catch (FileNotFoundException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       } catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }
       
       
   }
}

客户端代码

package com.apesource.demo;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class CilentImageTest {
    public static void main(String[] args) {
        // 本地图片地址
        String path = "E:\\我的QQ接受文件\\MobileFile\\IMG_20191118_112813.jpg";

        try {
            Socket socket = new Socket("192.168.137.1", 8030);
            // 向服务器发送数据
            OutputStream outputStream = socket.getOutputStream();
            // 获取本地图图片信息
            BufferedInputStream bfs = new BufferedInputStream(new FileInputStream(path));
            byte[] data = new byte[1024];
            int length = -1;
            // 写出到服务器
            while ((length = bfs.read(data)) != -1) {
                outputStream.write(data);
            
            }
            // 标记上传完成
            socket.shutdownOutput();

            // 获取服务器的上传成功
            InputStream inputStream = socket.getInputStream();

            data = new byte[1024];
            int x = inputStream.read(data);
            String str = new String(data, 0, x);
            System.out.println(str);
            bfs.close();
            socket.close();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

基于UDP协议的数据传送

无需建立连接,一次发送
DatagramSocket类创建套接字,无明显的客户端和服务端之分.接受方就是服务端,发送方就是客户端.
服务器端往往需要监听端口号,客户端往往要知道发送的IP地址和端口号
DatagramPacket类,将数据打包并发送
服务端往往调用recive()方法,客户端往往使用send方法.

创建套接字,绑定端口,创建空的数据包

//绑定端口号
DatagramSocket datagramSocket = new DatagramSocket(8020);
byte[] data = new byte[1024];
// 创建空的数据包,构造方法字节数组,字节长度
DatagramPacket reciveDatagramPacket = new DatagramPacket(data, data.length);

接受数据

datagramSocket.receive(reciveDatagramPacket );

解析数据包信息


            // 1获取发送的地址
            InetAddress sendinetAddress = reciveDatagramPacket.getAddress();

            // 2获取数据
            byte[] datax = reciveDatagramPacket.getData();

            // 3获取长度
            int length = reciveDatagramPacket.getLength();
            
            //将字节数组转化为String
             
            String str = new String(datax,0,length)

同样要创建DatagramSocket

DatagramSocket datagramSocket = new DatagramSocket()

数据打包发送,数据内容(字节数组),数据长度,服务端地址,端口号

//将发送的数据,发送的地址,发送的端口号,全部打包到DatagramPacket数据包
            DatagramPacket sendDatagramPacket = new DatagramPacket(data, data.length,sendInetAddress,8020);

发送数据

//使用DatagramSocket发送数据包DatagramPacket
            datagramSocket.send(sendDatagramPacket);

Java爬虫示例(多线程)

package com.apesource.demoURL;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

public class URLDemo2 {
    public static void main(String[] args) {
        try {
            // 获取网页的URL
            URL webURL = new URL("https://book.douban.com/");

            // 获取连接
            HttpsURLConnection httpURLConnection = (HttpsURLConnection) webURL.openConnection();
        
            // 读取网页字符信息
            BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(httpURLConnection.getInputStream(), "utf-8"));

            // 循环读取

            String line = null;
            while ((line = bufferedReader.readLine()) != null) {
                int suffix = line.indexOf(".jpg");
                if (line.indexOf("<img") > 0 && suffix > 0) {
                    // 截取图片的src
                    String src = line.substring(line.indexOf("https"), suffix + 4);
                    System.out.println(src);
                    // 多线程下载图片

                    // 创建线程
                    Thread thread = new Thread(new LoadImageThread(src));
                    thread.start();
                }
            }
        } catch (MalformedURLException e) {

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

            e.printStackTrace();
        }
    }

}

class LoadImageThread implements Runnable {
    private String src;

    public LoadImageThread(String src) {
        this.src = src;

    }

    @Override
    public void run() {

        try {
            // 创建图片的URL
            URL imgURL = new URL(src);
            // 获取连接
            HttpsURLConnection connection = (HttpsURLConnection) imgURL.openConnection();
            // 读取图片
            BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());

            // 获取文件名
            String name = this.src.substring(this.src.lastIndexOf("/") + 1);

            // 写入本地
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\Image\\Test" + name));

            byte[] dta = new byte[1024];
            int len = -1;
            while ((len = bis.read(dta)) != -1) {
                bos.write(dta, 0, dta.length);
            }
            bos.close();
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

上一篇 下一篇

猜你喜欢

热点阅读