JavaSE01_Day05(下)-Socket网络编程(C/S、B/S、TCP、UDP、Socket概述、聊天室案例(一、二))

一、Socket网络编程

1.1 C/S和B/S架构

  • C/S:client/server,客户端/服务端

  • B/S:browser/server,浏览器/服务端,浏览器本质来说也是一个标准的客户端。

1.2 TCP和UDP(面试题)

  • TCP协议:全称传输控制协议,其实它是一种面向连接的,并且可靠的,底层基于字节流进行传输数据的协议。传输数据的时候因为需要保证将数据信息完全的传输到目标位置,所有在这里它具有传输速度慢,占用资源多的相关缺点,优点就是传输数据的大小不受限制,并且可以将数据完整的进行传输。

eg:文件的传输,TCP协议底层是应用了三次握手(发送、接收、响应)

  • UDP协议:UDP协议主要应用于数据传输的实时性时使用,传输数据的速度较快,占用资源少,数据传输的的大小一般是64之内的数据。例如经常使用的微信通话,腾讯会议的使用上。使用UDP协议也会带来一些弊端,当遇到网络问题时,可能在网络异常时传递的数据就无法被接收到,当恢复网络以后,就会从网络状态ok后的情况进行数据的传输。

  • 补充即时通讯常用的网站:腾云、环信

1.3 Socket概述

       Socket中文含义"套接字",主要使用Socket描述IP地址和端口号,是一个通信链的句柄。应用程序通常使用Socket向网络发出请求或者应答。

1.4 聊天室案例一

业务场景:使用Java的Socket实现客户端和服务器端之间的连接,并使客户端向服务端发送一条消息。

客户端服务端
客户端向服务端发送“您好,服务端!!!” 服务端接收客户端信息,并显示在控制台中


Server端

 package cn.tedu.socket;
 
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.ServerSocket;
 import java.net.Socket;
 
 /**
  * 聊天室服务器端案例一
  * @author cjn
  *
  */
 public class Server {
     /*
      * 声明ServerSocket属性
      * 服务端使用的socket对象是ServerSocket,
      * 需要通过该对象进行申请服务的端口号,如果
      * 服务器端需要获取客户端发送的数据消息,
      * 需要和客户端书写的端口号一致,只有这样
      * 才可以进行监听到客户端所发送的消息
      */
     private ServerSocket serverSocket;
     
     /**
      * 添加构造器方法,用于对属性的初始化操作
      * @param args
      */
     public Server() {
         try {
             //启动类以后,进行对ServerSocket进行初始化
             System.out.println("服务器端正在启动...");
             //创建ServerSocket实例以后需要指定端口号
             serverSocket = new ServerSocket(8888);
             System.out.println("服务器端启动成功!!!");
        } catch (IOException e) {
             e.printStackTrace();
        } catch (Exception e) {
             e.printStackTrace();
        }
         
    }
 
     /**
      * 用于获取输入流对象,并且接收客户端发送的消息
      * @param args
      * @throws IOException
      */
     public void start() {
         try {
             System.out.println("等待客户端连接...");
             /*
              * 连接客户端,ServerSocket提供了一个accept接收客户端连接的方法
              * accept方法本身也是一个阻塞方法,没有客户端连接时会一直等待客户端连接
              */
             Socket socket = serverSocket.accept();
             System.out.println("一个客户端连接完毕!!!");
             //通过socket实例获取输入流对象
             InputStream is = socket.getInputStream();
             //流连接进行优化读取数据
             InputStreamReader isr = new InputStreamReader(is);//字符转换流
             BufferedReader br = new  BufferedReader(isr);//缓冲字符输出流
             //按行读取数据
             String message = br.readLine();
             //打印客户端发送过来的消息数据
             System.out.println("服务端接收到客户端发送的消息是:"+message);
             
        } catch (IOException e) {
             e.printStackTrace();
        } catch (Exception e) {
             e.printStackTrace();
        }
    }
     
     public static void main(String[] args) {
         Server server = new  Server();
         server.start();
    }
 
 }

Client端

 package cn.tedu.socket;
 /**
  * 聊天室客户端案例一
  * @author cjn
  *
  */
 
 import java.io.BufferedWriter;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.net.Socket;
 
 public class Client {
     /*
      * 声明Socket属性,用于客户端向服务器端发送数据,
      * Socket内部封装了TCP协议,是一个安全可靠协议
      */
     private Socket socket;
     
     /**
      * 添加客户端无参构造器,用于对属性的初始化操作
      * @param args
      */
     public Client() {
         try {
             System.out.println("开始连接服务端...");
             /*
              * Socket第一个参数代表的是服务器端的IP
              *       第二个参数代表的是服务器端的端口号
              *       127.0.0.1
              */
             socket = new Socket("localhost", 8888);
             System.out.println("连接服务端成功!!!");
        } catch (Exception e) {
             e.printStackTrace();
        }
    }
 
     /**
      * 客户端向服务器端写出数据的方法
      * @param args
      */
     public void start() {
         try {
             //从socket对象中进行获取输出流对象
             OutputStream os = socket.getOutputStream();
             //使用流连接的方式,使用高级流进行数据的写出
             OutputStreamWriter osw = new OutputStreamWriter(os);//字符转换流
             BufferedWriter bw = new BufferedWriter(osw);//字符缓冲流
             PrintWriter pw = new PrintWriter(bw,true);//自动行刷新
             //向服务端发送数据
             pw.println("您好,服务器端!!!");
             
        } catch (Exception e) {
             e.printStackTrace();
        }
    }
     
     public static void main(String[] args) {
         Client client = new Client();
         client.start();
    }
 
 }

测试结果:

切换服务端与客户端

(1)客户端控制台:

 开始连接服务端...
 连接服务端成功!!!

(2)服务器端控制台:

 服务器端正在启动...
 服务器端启动成功!!!
 等待客户端连接...
 一个客户端连接完毕!!!
 服务端接收到客户端发送的消息是:您好,服务器端!!!

1.5 聊天室案例二

业务功能:希望基于聊天室案例一的功能基础之上,可以让客户端不断的向服务器端发送消息。

Client客户端的start方法进行修改

     /**
      * 客户端向服务器端写出数据的方法
      * @param args
      */
     public void start() {
         try {
             //从socket对象中进行获取输出流对象
             OutputStream os = socket.getOutputStream();
             //使用流连接的方式,使用高级流进行数据的写出
             OutputStreamWriter osw = new OutputStreamWriter(os);//字符转换流
             BufferedWriter bw = new BufferedWriter(osw);
             PrintWriter pw = new PrintWriter(bw,true);
             /**********下面的内容进行了修改:循环写出**********/
             //向服务端发送数据
             Scanner scan = new Scanner(System.in);
             while(true) {
                 //不断的可以向服务器端发送消息
                 String message = scan.nextLine();
                 pw.println(message);
            }
             
        } catch (Exception e) {
             e.printStackTrace();
        }
    }

Server服务器端的start方法进行修改:

     /**
      * 用于获取输入流对象,并且接收客户端发送的消息
      * @param args
      * @throws IOException
      */
     public void start() {
         try {
             System.out.println("等待客户端连接...");
             /*
              * 连接客户端,ServerSocket提供了一个accept接收客户端连接的方法
              * accept方法本身也是一个阻塞方法,没有客户端连接时会一直等待客户端连接
              */
             Socket socket = serverSocket.accept();
             System.out.println("一个客户端连接完毕!!!");
             //通过socket实例获取输入流对象
             InputStream is = socket.getInputStream();
             //流连接进行优化读取数据
             InputStreamReader isr = new InputStreamReader(is);//字符转换流
             BufferedReader br = new  BufferedReader(isr);//缓冲字符输出流
             //按行读取数据
             //String message = br.readLine();
             /**********下面内容进行了修改:循环读入**********/
             String message;
             while ((message = br.readLine()) != null) {
                 //打印客户端发送过来的消息数据
                 System.out.println("服务端接收到客户端发送的消息是:"+message);
            }
             
        } catch (IOException e) {
             e.printStackTrace();
        } catch (Exception e) {
             e.printStackTrace();
        }
    }

 

posted @ 2021-06-26 23:24  Coder_Cui  阅读(384)  评论(0编辑  收藏  举报