高级编程--第六章 网络编程

1、目标

理解网络相关概念

会使用基于TCP协议的Socket编程

会使用基于UDP协议的Socket编程

2、IP地址

什么是IP地址?为什么需要IP地址?

两台计算机通信,双方都必须有地址,而这个地址就是Ip地址

IP地址(Internet Protocol)

唯一表示网络上的每一台计算机

IP地址的组成

32为,由4个8位二进制数组成

IP地址 = 网络地址 + 主机地址

网络地址: 标识计算机或网络设备所在的网段

主机地址: 标识特定主机或网络设备

IP地址的配置和检测

查看IP地址,检测网络是否畅通

查看本机的IP地址

可以使用命令 ifconfig

测试网络是否畅通

命令: ping 目标IP地址

DNS域名解析

DNS:Domain Name System,域名系统

访问网站的时候为什么输入的是网址而不是IP地址?

域名系统(DNS)就是起到网址与IP地址之间转换的作用。当用户在浏览器中输入网址后,DNS服务器会将这个易于记忆的网址转换成服务器对应的IP地址,然后浏览器才能通过这个IP地址找到并访问网站。所以,虽然最终访问的是IP地址指向的服务器,但是用户界面使用的是更加友好的网址。

网络服务器

通常指在网络环境下,具有较高计算能力,能够提供用户服务功能的计算机

网络通信协议

为了在网络中不同的计算机之间进行通信而建立的规则、标准或约定的集合

Socket

什么是Socket?

两台电脑之间的交互可以想象成物流运送快递的过程,而物流在运送的过程中都会经过中转站,这个中转站我们就可以看成是一个Socket。而在网络编程中,网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

通信链路的端点就被称为"套接字" (英文名Socket)

是提供给应用程序的接口

java.net包

Socket
ServerSocket
DatagramPacket
DatagramSocket
InetAddress

基于TCP协议的Socket编程

什么是TCP?

TCP是(Tranfer Control Protocol)的简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建立连接,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。

TCP的三次握手

建立起一个TCP连接需要经过"三次握手":第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求。

基于TCP协议的Socket网络通信

用来实现双向安全连接网络通信

Socket通信模型

进行网络通信时,Socket需要借助数据流来完成数据的传递工作

Socket网络编程一般可以分为如下步骤进行

Socket中实现对象的传递

传递对象信息

序列化

ObjectOutputStream  oos = new  ObjectOutputStream(...);
oos.writeObject(...);

ObjectInputStream  ois = new  ObjectInputStream(...);
Object = ois.readObject();

多线程处理多请求

实现多客户请求

采用多线程的方式,一个专门负责监听的应用主服务程序

一个专门负责处理请求的线程程序

基于UDP协议的Socket编程

|-----------|----------|-----------|
| | TCP | UDP |
| 是否连接 | 面向连接 | 面向非连接 |
| 传输可靠性 | 可靠 | 不可靠 |
| 速度 | | |

基于UDP协议的Socket网络编程步骤

练习

练习一

需求说明模拟用户登录的功能实现客户发送登录用户信息,服务器端显示登录信并响应给客户端登录成功

客户端

package exercise01;

import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

/**
 * @Author: Insight
 * @Description: TODO
 * @Date: 2024/9/9 17:07
 * @Version: 1.0
 */

public class client {
    public static void main(String[] args) {
        try {
            Socket sk = new Socket("127.0.0.1",8088);
            OutputStream os = sk.getOutputStream();
            String loginname = "";
            String loginpwd = "";
            String loginmsg = "";
            Scanner sc = new Scanner(System.in);
            System.out.println("欢迎来到登录系统");
            System.out.print("请输入用户名");
            loginname = sc.next();
            System.out.println("请输入密码");
            loginpwd = sc.next();

            loginmsg  = loginname + ";" + loginpwd;
            os.write(loginmsg.getBytes());

            sk.shutdownOutput();
            os.close();
            sk.close();

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

服务器端

package exercise01;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;

/**
 * @Author: Insight
 * @Description: TODO
 * @Date: 2024/9/9 17:09
 * @Version: 1.0
 */

public class Server {
    public static void main(String[] args) {
        try {
            ServerSocket ssk = new ServerSocket(8088);
            Socket sk = ssk.accept();
            InputStream is = sk.getInputStream();
            System.out.println(is.available());
            byte[] b = new byte[1024];
            System.out.println(is.read(b));
            String msg = new String(b,"UTF-8");
            System.out.println(msg);

            is.close();
            sk.close();
            ssk.close();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
    }
}

练习二

需求说明升级前一个上机内容,实现多客户端用户登录分析创建服务器端线程类,run()方法中实现对一个请求的响应处理修改服务器端代码,实现循环监听状态服务器端每监听到一个请求,创建一个处理线程

LoginThread

package exercise03;

import java.io.*;
import java.net.Socket;

/**
 * @Author: Insight
 * @Description: TODO
 * @Date: 2024/9/10 15:23
 * @Version: 1.0
 */

public class LoginThread extends Thread{
    private Socket socket;

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

    @Override
    public void run() {
        InputStream is= null;
        ObjectInputStream ois = null;
        OutputStream os = null;
        BufferedWriter bw = null;
        try {
            is = socket.getInputStream();
            ois  = new ObjectInputStream(is);

            User u = (User) ois.readObject();

            System.out.println(u.toString());
            System.out.println("用户:" + u.getUsername() + " 登陆成功!!");

//            os = socket.getOutputStream();
//            bw = new BufferedWriter(new OutputStreamWriter(os));
//
//            bw.write("登陆成功!!!");
//
//            bw.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

User

package exercise03;

import java.io.Serializable;

/**
 * @Author: Insight
 * @Description: TODO
 * @Date: 2024/9/10 15:23
 * @Version: 1.0
 */

public class User implements Serializable {
    private String username;
    private String userpwd;

    public User(String username, String userpwd) {
        this.username = username;
        this.userpwd = userpwd;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUserpwd() {
        return userpwd;
    }

    public void setUserpwd(String userpwd) {
        this.userpwd = userpwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", userpwd='" + userpwd + '\'' +
                '}';
    }
}

UserClient01

package exercise03;

import java.io.*;
import java.net.Socket;

/**
 * @Author: Insight
 * @Description: TODO
 * @Date: 2024/9/10 15:23
 * @Version: 1.0
 */

public class UserClient01 {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream os = null;
        ObjectOutputStream oos = null;

        InputStream is= null;
        BufferedReader br = null;
        try {
            socket = new Socket("127.0.0.1",8088);
            os = socket.getOutputStream();
            oos = new ObjectOutputStream(os);
            User u = new User("admin","admin");
            oos.writeObject(u);
            socket.shutdownOutput();

            is = socket.getInputStream();
            br = new BufferedReader(new InputStreamReader(is));
//            byte[] b = new byte[1024];

//            String str = new String(b);
            System.out.println(br.readLine());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                oos.close();
                os.close();
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}

UserClient02

package exercise03;

import java.io.*;
import java.net.Socket;

/**
 * @Author: Insight
 * @Description: TODO
 * @Date: 2024/9/10 15:23
 * @Version: 1.0
 */

public class UserClient02 {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream os = null;
        ObjectOutputStream oos = null;

        InputStream is= null;
        BufferedReader br = null;
        try {
            socket = new Socket("127.0.0.1",8088);
            os = socket.getOutputStream();
            oos = new ObjectOutputStream(os);
            User u = new User("admin1","admin1");
            oos.writeObject(u);
            socket.shutdownOutput();

            is = socket.getInputStream();
            br = new BufferedReader(new InputStreamReader(is));
//            byte[] b = new byte[1024];

//            String str = new String(b);
            System.out.println(br.readLine());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                oos.close();
                os.close();
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

UserServer

package exercise03;

import exercise01.Server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @Author: Insight
 * @Description: TODO
 * @Date: 2024/9/10 15:23
 * @Version: 1.0
 */

public class UserServer {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        try {

            serverSocket = new ServerSocket(8088);
            while(true){
                socket = serverSocket.accept();
                LoginThread loginThread = new LoginThread(socket);
                loginThread.start();
            }

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

练习三

需求说明实现客户咨询问题,客服人员答复问题分析咨询时,客户是发送方,客服人员是接收方答复时,客服人员是发送方,客户是接收方,实现思路和咨询时相同

客服回复:server

package exercise04;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.Scanner;

/**
 * @Author: Insight
 * @Description: 客服回复   这里通过将服务器端设定为客服端来实现二者对话
 * @Date: 2024/9/10 15:51
 * @Version: 1.0
 */

public class ServiceTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String reply = "";
        try {
            //UDPsocker链接  创建连接端口,默认ip为本地ip
            DatagramSocket datagramSocket = new DatagramSocket(8088);
            //接收数据包   创建DatagramPacket来创建接收信息的盒子
            byte[] b = new byte[1024];
            DatagramPacket datagramPacket = new DatagramPacket(b,b.length);
            do {
                //接收信息  通过atagramSocket.receive来将客户端传递的信息存入datagramPacket中
                datagramSocket.receive(datagramPacket);
                //读取出datagramPacket中的信息
                String str1 = new String(datagramPacket.getData(),0,datagramPacket.getLength());
                System.out.println("客服回复:" + str1);
                if (str1 != null){
                    //给客户端回应
                    System.out.println("请输入内容");
                    reply = sc.next();
                    byte[] b1 = reply.getBytes();
                    //获取客户端地址   通过getSocketAddress来获取客户端的ip地址,以便重新发回信息
                    SocketAddress sa = datagramPacket.getSocketAddress();
                    //打包信息  将需要回复的信息存入DatagramPacket中,并发回信息
                    DatagramPacket datagramPacket1 = new DatagramPacket(b1,0,b1.length,sa);
                    datagramSocket.send(datagramPacket1);
                }

                if(reply.equals("再见")) {
                    break;
                }

            }while(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

客户询问:Client

package exercise04;

import java.net.*;
import java.util.Scanner;

/**
 * @Author: Insight
 * @Description: TODO
 * @Date: 2024/9/10 15:51
 * @Version: 1.0
 */

public class UserClient01 {
    public static void main(String[] args) {
        System.out.println("客户咨询0.0.0.0.");
        Scanner sc= new Scanner(System.in);
        String ask = "";
        do {
            //开始询问
            System.out.println("请输入您要咨询的问题");
            ask = sc.next();

            byte[] b = ask.getBytes();

//            DatagramPacket datagramPacket = new DatagramPacket(b,0,b.length);
            DatagramSocket socket=null;

            InetAddress ia= null;

            try {
                ia = InetAddress.getByName("127.0.0.1");
                //打包信息发送
                DatagramPacket datagramPacket = new DatagramPacket(b,0,b.length,ia,8088);
                socket = new DatagramSocket();
                //发送消息
                socket.send(datagramPacket);


                //接收回复信息
                byte[] b1= new byte[1024];


                DatagramPacket datagramPacket1 = new DatagramPacket(b1,0,b1.length);
                socket.receive(datagramPacket1);
                String str1 = new String(datagramPacket.getData(),0,datagramPacket.getLength());
                System.out.println("客服回复:" + str1);
            } catch (Exception e) {
                e.printStackTrace();
            }

            if(ask.equals("再见")) {
                break;
            }

        }while(true);
    }
}
相关推荐
m0_571957582 小时前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
一点媛艺3 小时前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风3 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生4 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功4 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2344 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨4 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
老猿讲编程4 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk5 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*5 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go