17_网络编程基础

2020-12-19  本文已影响0人  真是个点子王

InetAddress

static InetAddress getLocalHost()
* 获得本地主机IP地址对象。
static InetAddress getByName(String host)
* 根据IP地址字符串或主机名获得对应的IP地址对象。
String getHostName()
* 获得主机名。
String getHostAddress()
* 获得IP地址字符串。
public class MyTestAddress {
    public static void main(String[] args) throws Exception {
        InetAddress address = InetAddress.getLocalHost();
        System.out.println(address.getHostAddress());
        System.out.println(address.getHostName());

        InetAddress address1 = InetAddress.getByName("www.baidu.com");
        System.out.println(address1.getHostAddress());
        System.out.println(address1.getHostName());
    }
}

UDP通信

发送端用构造器:
new DatagramPacket(byte[] buf, int length, InetAddress address, int port)
创建发送端数据包对象
 * buf:要发送的内容,字节数组
 * length:要发送内容的长度,单位是字节
 * address:接收端的IP地址对象
 * port:接收端的端口号

接收端用构造器:
new DatagramPacket(byte[] buf, int length)
  * 创建接收端的数据包对象
  * buf:用来存储接收到内容
  * length:能够接收内容的长度

常用方法
  int getLength()
  * 获得实际接收到的字节个数
- 构造器
new DatagramSocket() 
 * 创建发送端的Socket对象,系统会随机分配一个端口号。
new DatagramSocket(int port) 
 * 创建接收端的Socket对象并指定端口号

- 类成员方法
void send(DatagramPacket dp)
 * 发送数据包
void receive(DatagramPacket dp) 
 * 接收数据包
// 服务端
public class TestUDPServer {
    public static void main(String[] args) throws Exception{
        System.out.println("======== 服务端开始工作 ===========");
        byte[] buffer = new byte[1024 * 64];
        DatagramSocket socket = new DatagramSocket(8990);
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
        socket.receive(packet);
        String rs = new String(packet.getData());
        int length = packet.getLength();
        int port = packet.getPort();
        String address = packet.getAddress().getHostAddress();
        System.out.println("接收内容:" + rs);
        System.out.println("内容长度:" + length);
        System.out.println("地址:" + address+":"+port);
    }
}
// 客户端
public class TestUDPClient {
    public static void main(String[] args) throws Exception {
        System.out.println("======== 客户端开始工作 ===========");
        byte[] buffer = "You can really dance!".getBytes();
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length, InetAddress.getLocalHost(),8990);
        DatagramSocket socket = new DatagramSocket();
        socket.send(packet);
        socket.close();
    }
}

TCP通信

Socket

 // 构造器
 Sokcet(String host,int port)
/*
    根据ip地址字符串和端口号创建客户端Socket对像
*/

// 类常用方法
  OutputStream getOutputStream();  //获得字节输出流对象
  InputStream getInputStream();   //获取字节输入流对象

ServerSocket

// 构造器
public ServerSocket(int port);
// 方法
public Socket accept(); // 等待接收一个客户端的Socket管道连接请求,连接成功返回一个Socket对象

示例一:客户端发送一行数据,服务器接收一行数据

// 客户端
public class MyClientDemo {
    public static void main(String[] args) throws Exception {
        // 1.客户端请求于服务端的socket管道连接
        Socket socket = new Socket(InetAddress.getLocalHost().getHostAddress(),8888);

        // 2.从socket管道中获得一个字节输出流
        OutputStream os = socket.getOutputStream();

        // 3.把低级的字节输出流,包装成高级的打印流
        PrintStream ps = new PrintStream(os);

        // 4.开始发消息
        ps.println("You can really dance!");
        ps.flush();
        System.out.println("客户端发送完毕");
    }
}

// 服务端
public class MyServerDemo {
    public static void main(String[] args) throws Exception {
        System.out.println("---------- 服务端启动 ------------");
        // 1.注册端口
        ServerSocket serverSocket = new ServerSocket(8888);

        // 2.开始接收客户端的Socket管道连接
        Socket socket = serverSocket.accept();

        // 3.从socket通信管道中得到一个字节输入流
        InputStream is = socket.getInputStream();

        // 4.把字节输入流转换成字符输入流
        Reader isr = new InputStreamReader(is);

        // 5.把字符输入流包装成缓冲字符输入流
        BufferedReader br = new BufferedReader(isr);

        // 6.按行读取消息
        String msg;
        if ((msg= br.readLine())!=null){
            System.out.println(msg);
        }
    }
}

示例二:服务端可以为多个客户端提供服务

// 服务端
public class MyServerTest {
    public static void main(String[] args) throws Exception{
        System.out.println("欢迎来到深夜激情聊天室");
        // 1. 绑定端口
        ServerSocket serverSocket = new ServerSocket(8888);
        while (true){
            // 2.开始等待客户端的Socket的管道连接
            Socket socket = serverSocket.accept();
            Thread thread = new ServerThread(socket);
            thread.start();
        }
    }
}

class ServerThread extends Thread{
    private Socket socket;
    public ServerThread(Socket socket) {
        this.socket = socket;
    }
    @Override
    public void run(){
        try {
            // 3. 从socket管道读入一个字节输入流
            InputStream is = socket.getInputStream();
            // 4. 将字节输入流装换字符输入流
            Reader isr = new InputStreamReader(is);
            // 5. 将字符输入流包装成一个缓冲字符输入流
            BufferedReader br = new BufferedReader(isr);
            // 6. 按行读取、打印
            String line;
            while( (line = br.readLine() ) != null ){
                System.out.println(socket.getRemoteSocketAddress() + ":" + line);
            }
        } catch (IOException e) {
            System.out.println(socket.getRemoteSocketAddress() + ": 下线了");
        }
    }
}

// 客户端
public class MyClientTest {
    public static void main(String[] args) throws Exception{
        // 1. 客户端请求于服务器的Socket管道连接
        Socket socket = new Socket(InetAddress.getLocalHost().getHostAddress(),8888);

        // 2. 从socket管道中获取一个字节输出流
        OutputStream os = socket.getOutputStream();

        // 3. 将字节输出流包装成一个打印输出流
        PrintStream ps = new PrintStream(os);

        // 4. 开始发消息
        while(true){
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入:");
            ps.println(sc.nextLine());
            ps.flush();
        }
    }
}

示例三:利用线程池优化

// Runnable类
// 并发任务的主逻辑
class ReaderClientRunnable implements Runnable {
    private Socket socket ;
    public ReaderClientRunnable(Socket socket) {
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            // 读取一行数据
            InputStream is = socket.getInputStream() ;
            // 转成一个缓冲字符流
            Reader fr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(fr);
            // 一行一行的读取数据
            String line = null ;
            while((line = br.readLine())!=null){ // 阻塞式的!!
                System.out.println("服务端收到了数据:"+line);
            }
        } catch (Exception e) {
            System.out.println("有人下线了");
        }
    }
}

// 线程池处理类
public class HandlerSocketThreadPool {
    // 线程池 
    private ExecutorService executor;
    // 线程池:3个线程  100个
    public HandlerSocketThreadPool(int maxPoolSize, int queueSize){
        executor = new ThreadPoolExecutor(
                maxPoolSize,
                maxPoolSize,
                120L, 
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(queueSize) );
    }
    
    public void execute(Runnable task){
        this.executor.execute(task);
    }
}

// 服务端
public class Server {
    public static void main(String[] args) {
        try {
            System.out.println("----------服务端启动成功------------");
            ServerSocket ss = new ServerSocket(9999);

            // 一个服务端只需要对应一个线程池
            HandlerSocketThreadPool handlerSocketThreadPool =
                    new HandlerSocketThreadPool(3, 100);

            // 客户端可能有很多个
            while(true){
                Socket socket = ss.accept() ;
                System.out.println("有人上线了!!");
                // 每次收到一个客户端的socket请求,都需要为这个客户端分配一个
                // 独立的线程 专门负责对这个客户端的通信!!
                handlerSocketThreadPool.execute(new ReaderClientRunnable(socket));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        try {
            // 1.客户端要请求于服务端的socket管道连接。
            // Socket(String host, int port)
            Socket socket = new Socket("127.0.0.1" , 9999);
            // 2.从socket通信管道中得到一个字节输出流
            OutputStream os = socket.getOutputStream();
            // 3.把低级的字节输出流包装成高级的打印流。
            PrintStream ps = new PrintStream(os);
            Scanner sc = new Scanner(System.in);
            while(true){
                System.out.print("请说:");
                String msg = sc.nextLine();
                ps.println(msg);
                ps.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

示例四:实现文件上传功能

// 客户端
public class MyClientDemo {
    public static void main(String[] args) throws Exception {

        String filepath = "src/23232.png";
        // 1. 获取与服务端的Socket管道连接
        Socket socket = new Socket(InetAddress.getLocalHost().getHostAddress(),8998);

        // 2. 从管道中获得一个字节输出流
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());

        // 3. 提取本机的图片上传给服务端
        // 4. 得到一个缓冲字节输入流与本地图片接通
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filepath));

        // 5. 定义一个字节数组
        byte[] buffer = new byte[1024];
        int len;
        while ( (len = bis.read(buffer)) != -1){
            bos.write(buffer,0,len);
        }

        bos.flush(); // 刷新图片到服务器
        bis.close();
        socket.shutdownOutput(); //通知服务端文件写入已经完成
        System.out.println("客户端图片已发送完毕");
        // 6. 从服务端接受响应消息
        BufferedReader bf = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        System.out.println(bf.readLine());
    }
}
// 服务端
public class MyServerDemo {
    public static final String DEST_FILE = "F:\\课程资源\\java进阶13天资料\\day11-Socket网络编程、NIO\\code\\Day11Demo\\TestPic\\";
    public static void main(String[] args) throws Exception{


        // 1. 绑定端口
        ServerSocket serverSocket = new ServerSocket(8998);

        while (true){
            // 2.开始等待客户端的Socket的管道连接
            Socket socket = serverSocket.accept();
            Thread thread = new ServerThread(socket);
            thread.start();
        }
    }
}

class ServerThread extends Thread{
    private Socket socket;

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

    @Override
    public void run(){
        try {
            System.out.println(socket.getRemoteSocketAddress() + ": 上线了");
            // 1.获得缓冲输入字节流,接收当前客户端发来的图片
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
            // 2.从bio管道中读取客户端发来的图片字节,写入到本地路径中
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(MyServerDemo.DEST_FILE+ UUID.randomUUID().toString()+".png"));
            byte[] buffer = new byte[1024];
            int len;
            while ((len = bis.read(buffer)) != -1){
                bos.write(buffer,0,len);
            }
            bos.flush();
            bos.close();
            // 4.得到一个字节输出流,直接包装成打印流
            PrintStream ps = new PrintStream(socket.getOutputStream());
            ps.println("I get it!");
            ps.flush();
            Thread.sleep(1);
        } catch (Exception e) {
            System.out.println(socket.getRemoteSocketAddress() + ": 下线了");
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读