• 2017年4月19号课堂笔记


    2017年4月19号   小雨  空气质量:轻度污染

    内容:基于TCP协议的socket网络编程,基于TCP协议的socket网络编程(单用户、多用户登陆)

    基于UDP协议的socket网络编程,U1项目思路讲解

    一、Socket网络编程步骤

    (一)基于TCP协议的socket网络编程的步骤

    01.建立连接
    02.打开socket关联的输入输出流
    03.数据流中读写数据
    04.关闭所有数据流和socket

    Socket 客户端C
    ServerSocket 服务器S
    C/S架构

    (二)基于UDP协议的socket网络编程的步骤

    01.利用DatagramPacket对象封装数据报
    02.利用DatagramSocket发送数据报
    03.利用DatagramSocket接收数据报
    04.利用DatagramPacket对象处理数据报


    DatagramPacket: 打包,拆包!
    是封装了数据报的数据,数据的长度,目标地址和目标端口!

    DatagramSocket: 接收,发送!
    接收和发送封装好的数据报!

    (三)TCP 和 UDP的区别

    01. 是否面向连接
    TCP面向连接! UDP面向非连接!
    02.传输的可靠性
    TCP安全可靠! UDP不可靠!
    03.传输的速度
    TCP慢! UDP快!

    二、基于TCP协议的socket网络编程(超市购物案例)

    老师代码:

    1)服务器 (超市)ServerSocket

    package cn.bdqn.supermarket;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;

    /**
    * 服务器 (超市)ServerSocket
    *
    */
    public class ServerSocketTest {

    public static void main(String[] args) {
    ServerSocket serverSocket = null; // 超市
    Socket socket = null; // 顾客
    InputStream stream = null; // 购物车
    BufferedReader br = null; // 收银员
    OutputStream os = null; // 服务员的回应语句
    try {
    // 在指定的位置开了一家超市
    serverSocket = new ServerSocket(8800);
    // 超市开门 等待顾客上门
    socket = serverSocket.accept();
    // 顾客开始购物 把东西 放进 购物车 内 输入流
    stream = socket.getInputStream();
    /**
    * 结账?
    * 01.需要 把购物车的东西 放到 收银台上 ===》商品的暂存处
    * 02.收银员 需要扫码 一次一个商品
    */
    br = new BufferedReader(new InputStreamReader(stream));
    String info = null;
    while ((info = br.readLine()) != null) { // 说明购物车还有商品
    System.out.println("顾客购买的商品是:" + info);
    }
    // 顾客结账完毕 准备带回
    socket.shutdownInput(); // 顾客没有离开超市 只是不购物!
    // 接收服务员的语句
    os = socket.getOutputStream();
    os.write("谢谢光临".getBytes());
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    // 关闭所有资源
    os.close();
    br.close();
    stream.close();
    socket.close();
    serverSocket.close();
    } catch (IOException e) {
    e.printStackTrace();
    }

    }

    }

    }

    2)客户端(顾客) Socket

    package cn.bdqn.supermarket;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.Socket;

    /**
    * 客户端(顾客) Socket
    *
    */
    public class SocketTest {

    public static void main(String[] args) {
    Socket socket = null; // 顾客
    OutputStream os = null; // 钱包
    InputStream is = null; // 收银员的语句
    BufferedReader br = null;
    try {
    // 顾客 去指定的超时 购物
    socket = new Socket("localhost", 8800);
    // 打开钱包,疯狂购物=====》花钱 !
    os = socket.getOutputStream();
    // 开始购物
    os.write("萨德".getBytes());
    // 购物完毕
    socket.shutdownOutput(); // 把钱包捂住!

    // 接收我们收银员的问候
    is = socket.getInputStream();
    br = new BufferedReader(new InputStreamReader(is));
    String info = null;
    while ((info = br.readLine()) != null) {
    System.out.println("收银员说:" + info);
    }

    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    try {
    // 关闭资源
    br.close();
    is.close();
    os.close();
    socket.close();
    } catch (IOException e) {
    e.printStackTrace();
    }

    }

    }

    }

    三、基于TCP协议的socket网络编程(多用户登陆)

    老师代码:

    1)用户登录需要的服务器 

    package cn.bdqn.loginThread;

    import java.net.ServerSocket;
    import java.net.Socket;

    public class ServerSocketTest {

    /**
    * 用户登录需要的服务器
    * 需要 服务器 循环 一直 监听 登录 用户信息
    * 而不是 只能监听一个用户!
    */
    public static void main(String[] args) {
    ServerSocket serverSocket = null;
    Socket socket = null;

    try {
    // 实例化我们的服务器
    serverSocket = new ServerSocket(8800);
    while (true) {
    socket = serverSocket.accept(); // 在循环里 一直监听 用户登录的信息
    LoginThread thread = new LoginThread(socket);
    thread.start(); // 多个用户 就是 多个线程
    }
    } catch (Exception e) {
    e.printStackTrace();
    }

    }

    }

    2)服务器监听需要的线程类

    package cn.bdqn.loginThread;

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.ObjectInputStream;
    import java.io.OutputStream;
    import java.net.Socket;

    /**
    *
    *服务器监听需要的线程类
    */
    public class LoginThread extends Thread {
    private Socket socket = null;

    /**
    * 每个用户都有属于自己的socket
    */
    public LoginThread(Socket socket) {
    this.socket = socket;
    }

    @Override
    public void run() {
    InputStream is = null;
    OutputStream os = null;
    /**
    * 需要接收 用户这个对象!! 而不是之前的字符串!!
    * 反序列化
    */
    ObjectInputStream ois = null;
    try {
    // 打开输入和输出流 接收用户的输入 给用户一个响应
    is = socket.getInputStream();
    os = socket.getOutputStream();
    ois = new ObjectInputStream(is);

    // 获取登录用户的信息
    User user = (User) ois.readObject();
    System.out.println("登录用户的用户名是:" + user.getName());
    System.out.println("登录用户的密码是:" + user.getPassword());
    // 关闭输入流
    socket.shutdownInput();

    // 服务器给客户端一个成功响应
    os.write("恭喜您!登录成功!".getBytes());
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    try {
    // 释放资源
    os.close();
    ois.close();
    is.close();
    socket.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

    }

    3)模拟登录用户的实体类

    package cn.bdqn.loginThread;

    import java.io.Serializable;

    /**
    *模拟登录用户的实体类
    */
    public class User implements Serializable {

    private String name; // 用户名
    private String password; // 密码

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public String getPassword() {
    return password;
    }

    public void setPassword(String password) {
    this.password = password;
    }

    public User(String name, String password) {
    super();
    this.name = name;
    this.password = password;
    }

    public User() {
    super();
    }

    @Override
    public String toString() {
    return "User [name=" + name + ", password=" + password + "]";
    }

    }

    4)真正用户的登录   客户端1

    package cn.bdqn.loginThread;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.ObjectOutputStream;
    import java.io.OutputStream;
    import java.net.Socket;

    public class SocketTest1 {

    /**
    * 真正用户的登录 客户端1
    */
    public static void main(String[] args) {
    Socket socket = null;
    InputStream is = null;
    OutputStream os = null;

    BufferedReader br = null; // 接收服务器的回应
    /**
    * 需要给服务器一个 对象 需要 序列化对象
    */
    ObjectOutputStream oos = null;

    try {
    socket = new Socket("localhost", 8800);
    // 打开输入输出流 给服务器 传递对象 接收 服务器的相应
    is = socket.getInputStream();
    os = socket.getOutputStream();

    // 序列化
    User user = new User("小黑1", "123456");
    oos = new ObjectOutputStream(os);
    oos.writeObject(user);
    socket.shutdownOutput(); // 关闭输出流

    // 接收服务器的相应
    br = new BufferedReader(new InputStreamReader(is));
    String info = null;
    while ((info = br.readLine()) != null) {
    System.out.println("服务器的响应是:" + info);
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    try {
    // 释放资源
    br.close();
    oos.close();
    os.close();
    is.close();
    socket.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    }

    }

    5)真正用户的登录   客户端2

    package cn.bdqn.loginThread;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.ObjectOutputStream;
    import java.io.OutputStream;
    import java.net.Socket;

    public class SocketTest2 {

    /**
    * 真正用户的登录 客户端2
    */
    public static void main(String[] args) {
    Socket socket = null;
    InputStream is = null;
    OutputStream os = null;

    BufferedReader br = null; // 接收服务器的回应
    /**
    * 需要给服务器一个 对象 需要 序列化对象
    */
    ObjectOutputStream oos = null;

    try {
    socket = new Socket("localhost", 8800);
    // 打开输入输出流 给服务器 传递对象 接收 服务器的相应
    is = socket.getInputStream();
    os = socket.getOutputStream();

    // 序列化
    User user = new User("小黑2", "123456");
    oos = new ObjectOutputStream(os);
    oos.writeObject(user);
    socket.shutdownOutput(); // 关闭输出流

    // 接收服务器的相应
    br = new BufferedReader(new InputStreamReader(is));
    String info = null;
    while ((info = br.readLine()) != null) {
    System.out.println("服务器的响应是:" + info);
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    try {
    // 释放资源
    br.close();
    oos.close();
    os.close();
    is.close();
    socket.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    }

    }

    四、基于TCP协议的socket网络编程(单用户登陆,举例现实中少有)

    老师代码:

    1)用户登录需要的服务器

    package cn.bdqn.login;

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.ObjectInputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;

    public class ServerSocketTest {

    /**
    * 用户登录需要的服务器
    */
    public static void main(String[] args) {
    ServerSocket serverSocket = null;
    Socket socket = null;
    InputStream is = null;
    OutputStream os = null;
    /**
    * 需要接收 用户这个对象!! 而不是之前的字符串!!
    * 反序列化
    */
    ObjectInputStream ois = null;

    try {
    // 创建serverSocket对象
    serverSocket = new ServerSocket(8800);
    // 监听 用户的登录
    socket = serverSocket.accept();
    // 打开输入和输出流 接收用户的输入 给用户一个响应
    is = socket.getInputStream();
    os = socket.getOutputStream();
    ois = new ObjectInputStream(is);

    // 获取登录用户的信息
    User user = (User) ois.readObject();
    System.out.println("登录用户的用户名是:" + user.getName());
    System.out.println("登录用户的密码是:" + user.getPassword());
    // 关闭输入流
    socket.shutdownInput();

    // 服务器给客户端一个成功响应
    os.write("恭喜您!登录成功!".getBytes());
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    try {
    // 释放资源
    os.close();
    ois.close();
    is.close();
    socket.close();
    serverSocket.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    }

    }

    2)真正用户的登录 客户端

    package cn.bdqn.login;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.ObjectOutputStream;
    import java.io.OutputStream;
    import java.net.Socket;

    public class SocketTest {

    /**
    * 真正用户的登录 客户端
    */
    public static void main(String[] args) {
    Socket socket = null;
    InputStream is = null;
    OutputStream os = null;

    BufferedReader br = null; // 接收服务器的回应
    /**
    * 需要给服务器一个 对象 需要 序列化对象
    */
    ObjectOutputStream oos = null;

    try {
    socket = new Socket("localhost", 8800);
    // 打开输入输出流 给服务器 传递对象 接收 服务器的相应
    is = socket.getInputStream();
    os = socket.getOutputStream();

    // 序列化
    User user = new User("小黑", "123456");
    oos = new ObjectOutputStream(os);
    oos.writeObject(user);
    socket.shutdownOutput(); // 关闭输出流

    // 接收服务器的相应
    br = new BufferedReader(new InputStreamReader(is));
    String info = null;
    while ((info = br.readLine()) != null) {
    System.out.println("服务器的响应是:" + info);
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    try {
    // 释放资源
    br.close();
    oos.close();
    os.close();
    is.close();
    socket.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    }

    }

    3)模拟登录用户的实体类

    package cn.bdqn.login;

    import java.io.Serializable;

    /**
    *模拟登录用户的实体类
    */
    public class User implements Serializable {

    private String name; // 用户名
    private String password; // 密码

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public String getPassword() {
    return password;
    }

    public void setPassword(String password) {
    this.password = password;
    }

    public User(String name, String password) {
    super();
    this.name = name;
    this.password = password;
    }

    public User() {
    super();
    }

    @Override
    public String toString() {
    return "User [name=" + name + ", password=" + password + "]";
    }

    }

    五、基于UDP协议的socket网络编程

    老师代码:

    1)服务器

    public class Service { // 服务器
    public static void main(String[] args) {
    DatagramPacket dp = null; //打包 和 拆包数据
    DatagramSocket ds = null; // 接收和 发送数据
    //创建一个包 给客户端响应
    DatagramPacket dpTo=null;
    try {
    byte [] buf=new byte[1024];
    //创建数据包的对象
    dp=new DatagramPacket(buf, buf.length);
    ds=new DatagramSocket(8800);
    //接收
    ds.receive(dp);
    //显示接收的信息 拆包
    String msg=new String(dp.getData(), 0, dp.getLength());
    //获取 对方的地址 客户端的信息
    System.out.println(dp.getAddress().getHostAddress()+"说====:"+msg);

    //回复给 客户端
    byte[] reply="您好!航母已经发货!".getBytes();
    // dp就是从客户端传来的信封 信封上肯定有 寄件人的地址
    SocketAddress address=dp.getSocketAddress();
    //打包成功
    dpTo=new DatagramPacket(reply, reply.length,address);
    //发送
    ds.send(dpTo);
    } catch (SocketException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }

    }

    }

    2)客户端:

    public class Client { //客户端
    public static void main(String[] args) {
    DatagramPacket dp = null; //打包 和 拆包数据
    DatagramSocket ds = null; // 接收和 发送数据
    //创建一个包 给服务器响应
    DatagramPacket dpTo=null;
    InetAddress address=null;
    try {
    //你在网上购物 要不要给客服 说你的地址
    byte[] say="买个航空母舰!".getBytes();
    //获取本机的地址!
    address = InetAddress.getByName("localhost");
    //打包
    dp=new DatagramPacket(say, say.length,address,8800);
    //发送
    ds=new DatagramSocket();
    ds.send(dp);

    //接收
    byte [] buf=new byte[1024];
    dpTo=new DatagramPacket(buf, buf.length);
    ds.receive(dpTo);
    //我们看客服给我们回复了 什么 拆包
    String reply=new String(dpTo.getData(),0,dpTo.getLength());
    System.out.println(dpTo.getAddress().getHostAddress()+"说===》"+reply);
    } catch (UnknownHostException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }


    }

    }

    六、作业(U1项目)思路讲解(下周五考试、答辩)

    1、信息都保留在xml格式文件中

    2、账单用txt文件保存(I/O流)

    3、套餐变更(标记)

    4、退网(请勿删除用户,仅删除用户名下信息)

    5、写完copy一份儿,优化代码并理清逻辑练习讲解

    6、有余力考虑加点儿不一样的功能

    七、老师辛苦了!

  • 相关阅读:
    Delphi 的字符及字符串[4] 字符串、字符指针与字符数组
    Delphi 的字符及字符串[5] 字符串与 Windows API
    WinAPI: FindWindow、FindWindowEx 查找窗口
    java LookAndFeel 美化 Substance使用
    持久化和对象关系映射ORM技术
    java 更换皮肤问题Cannot refer to a nonfinal variable inside an inner class defined in a different method
    java Swing可视化开发工具
    php ORM 持久层框架与简单代码实现
    生成Substance皮肤Menu项的代码
    三层架构实现
  • 原文地址:https://www.cnblogs.com/wsnedved2017/p/6733736.html
Copyright © 2020-2023  润新知