Socket网络编程-TCP&UDP

认真学完,相信你会有收获

文章目录

  • 1.网络编程概述
    • 1.1 什么是网络编程
      • 1.1.1 理解网络编程
      • 1.1.2 网络编程结构
    • 1.2 IP地址及端口号
  • 2.Java网络编程-Socket
    • 2.1 网络套接字(Socket)
    • 2.2 Socket入门案例
      • 2.2.1 编写并运行服务器端
      • 2.2.2 编写并运行客户端
      • 2.2.3 如何运行?
    • 2.3 Socket获取对方IP地址
      • 2.3.1 服务端编写
      • 2.3.2 客户端编写
    • 2.4 Socket服务端和单客户端多次通信
      • 需要实现的效果
      • 2.4.1 服务端编写
      • 2.4.2 客户端编写
    • 2.5 Socket服务端和多客户端多次通信
      • 2.5.1分析:
      • 2.5.2 需要实现的效果
      • 2.5.3 服务端编写
      • 2.5.4 处理各个客户端的线程类编写
  • 3.TCP和UDP协议
    • 3.1概述
    • 3.2UDP网络编程
      • 3.2.1 发送方
      • 3.2.2 接收方

1.网络编程概述

1.1 什么是网络编程


1.1.1 理解网络编程


  • 网络:万维网、局域网
  • 网络编程:程序部署在多台计算机上,通过网络相互访问。就是让程序在网络中可以传递数据。

是基于请求-响应的

Socket网络编程-TCP&UDP_第1张图片

1.1.2 网络编程结构


  • 请求/响应模式:基本上所有网络程序都是请求/响应模式的。请求/响应模式把网络程序分为服务器端程序和客户端程序。

  • 服务器端:永无休止的在运行,等待客户端的请求,然后向客户端做出响应。

  • 客户端:向服务器端发出请求,获得服务器端响应。

  • 举个例子:
    相信大多人的电脑上都装了“微信”,而我们安装的就是微信的客户端程序。也就是说客户端通常是多个。当我们登录、聊天时,都是在客户端向服务器端发出请求。而服务器端通常只有一个,他安装在一台或一组计算机上(集群)。

  • 总结服务器/客户端特点:

    • 客户端有多个,而服务器有一个,多个客户端访问同一个服务器。
    • 服务器被动等待请求,只要接收到请求,就会马上向客户端发出响应。
    • 客户端主动发送请求,服务器马上就会响应客户端。
  • 网络编程结构大致分为两种:B/S和C/S,主要区别是客户端程序的形式不同:

    • B/S:客户端是浏览器,例如淘宝、百度、京东等。
      • 程序升级只需要升级服务器端,客户端无需升级。
      • 安全性较差。
    • C/S:客户端需要单独安装,例如微信、英雄联盟等
      • 程序升级需要同时升级服务器端和客户端。
      • 安全性较好。

1.2 IP地址及端口号

当需要与某台计算机的某个应用程序建立连接时,必须要知道IP和端口号。


  • IP地址:计算机在网络中的唯一标识,相当于计算机的身份证。
    • 格式:255.255.255.255,其中每个段位的值是 0-255,其中 127.0.0.1 表示本机。
  • 端口号:用于确定某个进程的地址(相当于某台计算机中某个进程的身份证号)
    • 范围:0-65535,其中 0-1024 系统会占用。同一台计算机中,端口号不能重复。

Socket网络编程-TCP&UDP_第2张图片

2.Java网络编程-Socket


2.1 网络套接字(Socket)

网络套接字是两台计算机通信的端点。


可以理解为两部通话的手机。服务器端和客户端各有一个Socket对象,就好像各有一个手机一样,可以互相传输数据。

Socket网络编程-TCP&UDP_第3张图片

Socket之间通讯是使用IO流完成的。

每个Socket对象都有输入流和输出流对象,他们好比电话的听筒的话筒。其中输入流对应听筒,输出流对应话筒。

Socket网络编程-TCP&UDP_第4张图片

客户端使用OutputStream(话筒)向服务器端发送数据,服务器端使用InputStream(听筒)接收数据。反之服务器端使用OutputStream(话筒)发送数据,客户端使用InputStream(听筒)接收数据。

注意: 一个发送数据一个接收数据,必须是对应的。一方发送了数据,另一个方没有接收,或者一方接收等待中,另一个一直不发。这两种情况都无法完成数据的传输。

2.2 Socket入门案例

创建项目就不带你创建了。我们直接lou代码


Socket网络编程-TCP&UDP_第5张图片

2.2.1 编写并运行服务器端

代码执行完毕后会发现,卡住了,说明服务端启动成功,在等待客户端的连接。继续编写客户端运行后即可看到客户端发送的消息。

注意:两端获取的输入流和输出流不要关闭,否则会提前导致通信连接关闭

package com.manlu.service;

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

/**
 * @author 漫路
 */
public class ServerDemo1 {
     
    public static void main(String[] args) throws IOException {
     
        //1.创建服务器端                      12121表示服务端的端口号
        ServerSocket serverSocket = new ServerSocket(12121);
        //2.与客户端连接,连接成功将获取socket对象
        Socket socket = serverSocket.accept();
        System.out.println("与客户端连接成功");
        //3.读取客户端本次发送的数据
        InputStream is = socket.getInputStream();
        byte[] arr = new byte[1024];
        int len = is.read(arr);
        System.out.println(new String(arr,0,len));
        //4.使用完毕,关闭本次通信连接
        socket.close();
    }
}

2.2.2 编写并运行客户端

package com.manlu.customer;

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

/**
 * @author 漫路
 */
public class ClientDemo1 {
     
    public static void main(String[] args) throws IOException {
     
        //1. 创建客户端,和服务器创建连接
        Socket socket =  new Socket("127.0.0.1",12121);
        //2. 向服务器发送消息
        OutputStream os = socket.getOutputStream();
        os.write("客户端回应".getBytes("utf-8"));
        //3. 关闭本次通信
        socket.close();
    }
}

2.2.3 如何运行?

记得是先运行服务器端,如果先运行客户端,会报错误,找不到服务器端。

Socket网络编程-TCP&UDP_第6张图片

2.3 Socket获取对方IP地址


Socket网络编程-TCP&UDP_第7张图片

  • InetAddress类:
    • Socket类的getInetAddress()方法返回InetAddress类的对象,表示对方的IP地址。可以调用InetAddress类的getHostAddress()方法得到字符串表示的IP地址。

2.3.1 服务端编写

package com.manlu.service;

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

/**
 * @author 漫路
 */
public class ServerDemo2 {
     
    public static void main(String[] args) throws IOException {
     
        //1. 创建服务器端
        ServerSocket serverSocket = new ServerSocket(12122);
        //2. 等待客户端连接
        Socket accept = serverSocket.accept();
        //3. 获取客户端ip地址
        InetAddress inetAddress = accept.getInetAddress();
        System.out.println("客户端信息:"+inetAddress.getHostAddress());
        //4. 关闭连接
        accept.close();
    }
}

2.3.2 客户端编写

package com.manlu.customer;

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

/**
 * @author 漫路
 */
public class ClientDemo2 {
    public static void main(String[] args) throws IOException {
        //1. 创建客户端
        Socket socket = new Socket("127.0.0.1",12122);
        //2. 获取服务器端的ip地址
        InetAddress inetAddress = socket.getInetAddress();
        System.out.println("服务端信息:"+inetAddress.getHostAddress());
        //3. 关闭连接
        socket.close();
    }
}

2.4 Socket服务端和单客户端多次通信


Socket网络编程-TCP&UDP_第8张图片

需要实现的效果

  • 客户端:

Socket网络编程-TCP&UDP_第9张图片

  • 服务端:

Socket网络编程-TCP&UDP_第10张图片

2.4.1 服务端编写

package com.manlu.service;

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

/**
 * @author 漫路h
 */
public class ServerDemo3 {
     
    public static void main(String[] args) throws IOException {
     
        //1. 创建服务器端对象
        ServerSocket serverSocket = new ServerSocket(12123);
        //2. 等待和客户端连接
        Socket socket = serverSocket.accept();
        System.out.println("和客户端连接成功");
        //3. 获取输入、输出流、IP地址
        InputStream in = socket.getInputStream();//输入流
        OutputStream out = socket.getOutputStream();//输出流
        String ip = socket.getInetAddress().getHostAddress();//ip
        //4. 无限循环通信
        while (true){
     
            //4.1 读取信息
            byte[] arr = new byte[1024];
            int len = in.read(arr);
            String str = new String(arr,0,len);
            //4.2 判断信息
            if ("退出".equals(str)) {
     
                System.out.println("服务器端关闭");
                socket.close();
                break;//停止循环
            }else{
     
                System.out.println("服务器端接收到"+ip+"客户端信息: "+str);
                out.write("服务器端已接收到信息。".getBytes("utf-8"));
                out.flush();
            }
        }
    }
}

2.4.2 客户端编写

package com.manlu.customer;

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

/**
 * @author 漫路h
 */
public class ClientDemo3 {
     
    public static void main(String[] args) throws IOException {
     
        //1. 创建客户端
        Socket socket = new Socket("127.0.0.1", 12123);
        System.out.println("和服务器端连接成功");
        //2. 获得输入流、输出流、IP
        InputStream in = socket.getInputStream();
        OutputStream out = socket.getOutputStream();
        String ip = socket.getInetAddress().getHostAddress();
        Scanner scanner = new Scanner(System.in);//控制台输入
        //3. 无限循环通信
        while (true){
     
            //3.1 发送信息
            System.out.println("请输入信息: ");
            String str = scanner.nextLine();
            out.write(str.getBytes("utf-8"));
            out.flush();
            if ("退出".equals(str)) {
     
                System.out.println("客户端退出");
                break;
            }
            //3.2. 接收信息
            byte[] arr = new byte[1024];
            int len = in.read(arr);
            System.out.println("服务器端ip:"+ip);
            System.out.println("服务器端回应内容:"+new String(arr,0,len));
        }
    }
}

2.5 Socket服务端和多客户端多次通信

2.5.1分析:

如果需要一个服务器多个客户端,这就需要服务器端为每个客户端开启一个通讯线程。与客户端通讯的代码写在线程中,而主线程负责继续等待下一个客户端的连接。

Socket网络编程-TCP&UDP_第11张图片

对于多客户端聊天无需修改客户端代码,只需要修改服务器端代码即可。下面我们只编写服务器端。

Socket网络编程-TCP&UDP_第12张图片

2.5.2 需要实现的效果

服务端可以接收到不同的客户端发送的信息。客户端3和客户端4是一样的代码,复制一份即可。

  • 客户端3发送内容

Socket网络编程-TCP&UDP_第13张图片

  • 客户端4发送内容

Socket网络编程-TCP&UDP_第14张图片

  • 服务端接收内容

可以看到主服务器端并没没有关闭,还在等待客户端发送信息。关闭的只是一个一个对应客户端的服务器端线程。

Socket网络编程-TCP&UDP_第15张图片

2.5.3 服务端编写

package com.manlu.service;

import com.manlu.thread.SocketThread;

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

/**
 * @author 漫路h
 */
public class ServerDemo4 {
     
    public static void main(String[] args) throws IOException {
     
        //1. 创建服务器端对象
        ServerSocket serverSocket = new ServerSocket(12123);
        //2. 无限循环接收不同客户端信息
        while (true) {
     
            Socket socket = serverSocket.accept();
            new Thread(new SocketThread(socket)).start();//创建线程,并启动线程
        }
    }
}

2.5.4 处理各个客户端的线程类编写

package com.manlu.thread;

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

/**
 * @author 漫路h
 * 通信线程类
 */
public class SocketThread implements Runnable {
     

    //客户端对象
    private Socket socket;

    /**
     * 有参构造
     * @param socket
     */
    public SocketThread(Socket socket) {
     
        this.socket = socket;
    }

    /**
     * 线程
     */
    public void run() {
     
        try{
     
            System.out.println("和客户端连接成功");
            //3. 获得输入流、输出流、IP
            InputStream in = socket.getInputStream();//输入流
            OutputStream out = socket.getOutputStream();//输出流
            String ip = socket.getInetAddress().getHostAddress();//客户端IP
            //4. 无限循环通信
            while (true) {
     
                //4.1 读取客户端发送信息
                byte[] arr = new byte[1024];
                int len = in.read(arr);
                String str = new String(arr, 0, len);
                //4.2 判断信息
                if ("退出".equals(str)){
     
                    System.out.println("服务器端关闭");
                    socket.close();
                    break;
                }else{
     
                    System.out.println("接收到"+ip+"客户端信息:"+str);
                    out.write("服务器已接收到信息".getBytes("utf-8"));
                    out.flush();
                }
            }
        }catch ( IOException e){
     
            e.printStackTrace();
        }
    }
}

3.TCP和UDP协议


3.1概述

网络协议:是为了进行有效的网络传输,提前制定的数据传输标准和格式。

我们上面学习的Socket,是基于TCP的通讯协议。(即先建立连接,才能通讯)

  • TCP协议:全称(Transmission Control Protocol),翻译为:传输控制协议。

    • 特点:
        1. 需要先建立连接
        1. 可靠安全,不丢是数据,但是速度慢
  • UDP协议:全称(User Datagram Protocol),翻译为:用户数据报协议。

    • 特点:
        1. 无需建立连接
        1. 不可靠,可能丢失数据,但是速度快
  • TCP&UDP适应场景

    • 如果要传输的数据是可以偶尔丢失的,那么可以使用UDP协议,否则使用TCP协议。
    • 例如:
      • QQ聊天可以使用UDP协议,因为聊天偶尔丢失一条数据,也不会有太大影响。
      • 网上银行就不可以使用UDP了,因为一丢点数据都不能丢失,谁都不愿意存钱的时候丢了点钱,哈哈。

3.2UDP网络编程

现在先运行发送方也不会报错了,因为不管接收方能不能收到,我先发出去再说,然后如果接收方真的没有运行,那数据就丢了。

Socket网络编程-TCP&UDP_第16张图片

3.2.1 发送方

package com.manlu.udp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * @author 漫路
 * 发送方
 */
public class SenderDemo {
     
    public static void main(String[] args) throws Exception {
     
        //1. 创建socket对象
        DatagramSocket ds = new DatagramSocket();
        //2. 创建接收方的IP地址对象
        InetAddress ia = InetAddress.getByName("127.0.0.1");
        //3. 定义一个数组,用来保存待发送数据
        byte[] arr = "测试发送的数据".getBytes("utf-8");
        //4. 创建数据包类对象,用于封装要发送的数据、IP、端口号
        DatagramPacket dp = new DatagramPacket(arr, arr.length, ia, 12124);
        //5. 发送
        ds.send(dp);
        //6. 关闭socket对象
        ds.close();
    }
}

3.2.2 接收方

package com.manlu.udp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * @author 漫路
 * 接收方
 */
public class ReceiverDemo {
     
    public static void main(String[] args) throws Exception {
     
        //1. 创建socket对象,指明接收数据的端口号
        DatagramSocket ds = new DatagramSocket(12124);
        //2. 创建数据包类
        //2.1 创建一个字节数组,用于存储数据
        byte[] arr = new byte[1024];
        //2.2 创建数据包类,指明接收数据的数组
        DatagramPacket dp = new DatagramPacket(arr, arr.length);
        //3. 接收数据
        ds.receive(dp);
        String ip = dp.getAddress().getHostAddress();
        System.out.println("发送方ip:"+ip);
        System.out.println(new String(arr,"utf-8"));
        //4. 关闭socket
        ds.close();
    }
}

你可能感兴趣的:(Java,socket,java,网络,编程语言)