UDP数据报和TCP流套接字编程

UDP数据报套接字编程

1.DatagramSocket类

DatagramSocket 是UDP Socket,⽤于发送和接收UDP数据报。
DatagramSocket构造方法:
DatagramSocket():创建⼀个UDP数据报套接字的Socket,绑定到本机任意⼀个随机端⼝(⼀般⽤于客户端)
DatagramSocket(int port):创建⼀个UDP数据报套接字的Socket,绑定到本机指定的端⼝(⼀般⽤于服务端)
DatagramSocket方法:
void receive(DatagramPacket p):
从此套接字接收数据报(如果没有接收到数据报,该⽅法会阻塞等待)
void send(DatagramPacket p):从此套接字发送数据报(不会阻塞等待,直接发送)
void close():关闭此数据报

2.DatagramPacket类

DatagramPacket构造方法:
DatagramPacket(byte[] buf, int length):
构造⼀个DatagramPacket以⽤来接收数据报,接收的数据保存在字节数组(第⼀个参数buf)中,接收指定⻓度(第⼆个参数length)

DatagramPacket(byte[] buf, int offset, int length,SocketAddress address):构造⼀个DatagramPacket以⽤来发送数据报,发送的
数据为字节数组(第⼀个参数buf)中,从0到指定⻓度(第⼆个参数length)。address指定⽬的主机的IP和端⼝号

DatagramPacket方法:
InetAddress getAddress():从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址
int getPort():从接收的数据报中,获取发送端主机的端⼝号;或从发送的数据报中,获取接收端主机端⼝号
byte[] getData():获取数据报中的数据

3. InetSocketAddress类

构造UDP发送的数据报时,需要传⼊ SocketAddress ,该对象可以使⽤ InetSocketAddress来创建。
InetSocketAddress ( SocketAddress 的⼦类 )构造⽅法:
InetSocketAddress(InetAddress addr, int port):创建一个Socket地址,包含IP地址和端口号

构建服务端和客户端

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;

public class UDPEchosever {
    //创建服务端
    DatagramSocket socket;
    public UDPEchosever(int post) throws SocketException {
        if(post<1024||post>65535){
            throw new RuntimeException("端口号不符合条件");
        }
        socket=new DatagramSocket(post);
    }

    public void start() throws IOException {
        System.out.println("服务器已启动");
        while (true){
            //接收用户发来的数据
            DatagramPacket requestPacket = new DatagramPacket(new byte[1024], 1024);
            // 2. 接收数据
            socket.receive(requestPacket);
            // 3. 解析接收到的数据
            String request = new String(requestPacket.getData(), 0,
                    requestPacket.getLength(), "UTF-8");
            //接收响应
            String respose=count(request);
            //发送响应
            DatagramPacket resposeSock=new DatagramPacket(respose.getBytes(StandardCharsets.UTF_8),0,respose.length(),requestPacket.getSocketAddress());
            socket.send(resposeSock);
            System.out.printf("[%s:%d] request :%s,response=%s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,respose);
        }
    }
    public String count(String request){
        return request;
    }

    public static void main(String[] args) throws IOException {
        UDPEchosever udpEchosever=new UDPEchosever(8888);
        udpEchosever.start();
    }
}
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

public class UDPEchoclient {
    //创建客户端
    DatagramSocket socket;
    //定义端口号,IP地址
    String IP;
    int port;
    public UDPEchoclient (String IP,int port) throws SocketException {
        this.socket=new DatagramSocket();
        this.IP=IP;
        this.port=port;
    }
    public void start() throws IOException {
        System.out.println("客服端已启动");
        while (true){
            System.out.println("->");
            //发送内容
            Scanner scanner=new Scanner(System.in);
            String request=scanner.nextLine();
            if(request==null||request.isEmpty()){
                System.out.println("字符串不能为空");
            }
            //包装用户发送的内容
            //SocketAddress address = new InetSocketAddress(IP, port);
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(StandardCharsets.UTF_8),
                    0, request.getBytes().length, new InetSocketAddress(IP, port));
//            DatagramPacket datagramPacket=new DatagramPacket(request.getBytes(StandardCharsets.UTF_8),0,request.length(),
//                    new InetSocketAddress(IP,port));
            socket.send(requestPacket);
            //用DatagramPacket接收服务器的响应数据
            DatagramPacket revicesocket=new DatagramPacket(new byte[1024],1024);
            socket.receive(revicesocket);
            //解析发送来的数据
            String respose=new String(revicesocket.getData(),0, revicesocket.getLength(),"UTF-8");
            System.out.printf("request:%s,repost:%s",request,respose);
        }
    }

    public static void main(String[] args) throws IOException {
        //System.out.println("你好");
        UDPEchoclient udpEchoclient=new UDPEchoclient("127.0.0.1",8888);
        udpEchoclient.start();
    }
}

在这里插入图片描述

TCP流套接字编程

1. ServerSocket类

ServerSocket 构造⽅法:
ServerSokcet(int port):创建⼀个服务端流套接字Socket,并绑定到指定端⼝
ServerSocket方法:
Socket accept():开始监听指定端⼝(创建时绑定的端⼝),有客⼾端连接后,返回⼀个服务端Socket对象,并基于该Socket建⽴与客⼾端的连接,否则阻塞等待
void close():关闭此套接字

2.Socket类

Socket 是客⼾端Socket,或服务端中接收到客⼾端建⽴连接(accept⽅法)的请求后,返回的服务端Socket。
不管是客⼾端还是服务端Socket,都是双⽅建⽴连接以后,保存的对端信息,及⽤来与对⽅收发数据的。
Socket的构造方法:
Socket(String host, int port):创建⼀个客⼾端流套接字Socket,并与对应IP的主机
上,对应端⼝的进程建⽴连接
Socket方法:
InetAddress getInetAddress() 返回套接字所连接的地址
InputStream getInputStream() 返回此套接字的输⼊流
OutputStream getOutputStream() 返回此套接字的输出流

构建服务端和客户端

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

public class TCPEchoSever {
    ServerSocket socket;
    //定义客户端
    public TCPEchoSever(int pase) throws IOException {
        if(pase<1024||pase>65535){
            System.out.println("端口号不符合条件");
        }
       this.socket=new ServerSocket(pase);
    }
    public void start() throws IOException {
        System.out.println("服务器已启动,等待客服端连接");
        //循环接收连接需求
        while (true){
            Socket clientsocket=socket.accept();
            //创建一个方法去接收客服端的内容
            reviceports(clientsocket);

        }
    }
    public void reviceports(Socket clientsocket) throws IOException {

        System.out.printf("[%s %d] 客服端上线了\n",clientsocket.getInetAddress().toString(),clientsocket.getPort());
        //使用输出流和输入流进行接收
            try(InputStream inputStream= clientsocket.getInputStream();
                OutputStream outputStream= clientsocket.getOutputStream()){
                while (true) {
                    Scanner scanner = new Scanner(inputStream);//嵌入输入流
                    if (!scanner.hasNextLine()) {
                        System.out.printf("[%s %d] 客服端下线了",clientsocket.getInetAddress().toString(),clientsocket.getPort());
                        break;
                    }
                    //获取用户发来的内容
                    String request = scanner.nextLine();
                    //对内容进行计算响应
                    String respose = Calculation(request);
                    //把响应写入输出流
                    PrintWriter printWriter = new PrintWriter(outputStream);
                    printWriter.println(respose);
                    //刷新缓冲区
                    printWriter.flush();
                    //打印
                    System.out.printf("[%s:%d] request=%s,respose=%s\n", clientsocket.getInetAddress().toString(), clientsocket.getPort(), request, respose);
                }
            }
    }
    protected String Calculation(String respose){
        return respose;
    }

    public static void main(String[] args) throws IOException {
        TCPEchoSever tcpEchoSever=new TCPEchoSever(8888);
        tcpEchoSever.start();
    }
}
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class TCPEchoClient {
    //创建客服端
    Socket socket;
    String IP;
    int port;
    public TCPEchoClient(String IP, int port) throws IOException {
        if (IP == null || IP.isEmpty()) {
            throw new RuntimeException("IP不能为空");
        }
        if (port < 1024 || port > 65535) {
            throw new RuntimeException("端口号不符合要求");
        }
        socket = new Socket(IP, port);
    }

    public void start() {
        System.out.println("客服端已启动");
            try (InputStream inputStream = this.socket.getInputStream();
                 OutputStream outputStream = this.socket.getOutputStream()) {
                while (true) {
                    Scanner scanner = new Scanner(System.in);
                    String request = scanner.nextLine();
                    if (request.isEmpty() || request == null) {
                        System.out.println("发送内容不能为空");
                    }
                    PrintWriter printWriter = new PrintWriter(outputStream);
                    //把数据写入输出流
                    printWriter.println(request);
                    printWriter.flush();
                    //接收服务端发送来的数据
                    Scanner scan = new Scanner(inputStream);
                    String respose = scan.nextLine();
                    System.out.println("request:" + request + "repose:" + respose);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
                }

    public static void main(String[] args) throws IOException {
        TCPEchoClient tcpEchoClient=new TCPEchoClient("127.0.0.1",8888);
        tcpEchoClient.start();
    }
}

扩展

连接的端口号自定义在1024-65535间,自己定义统一就行,都是在服务端修改,客服端不发生修改

对话形式

import java.io.IOException;
import java.util.Scanner;

public class TCPEchoexchange extends TCPEchoSever {

    public TCPEchoexchange(int pase) throws IOException {
        super(pase);
    }

    @Override
    protected String Calculation(String request) {
        //打印发送来的内容
        System.out.println(request);
        System.out.println("请用户输入回应内容");
        while (true){
            Scanner scanner=new Scanner(System.in);
            String respose=scanner.nextLine();
            if(respose==null||respose.isEmpty()){
                System.out.println("输入内容不能为空");
            }
            return respose;
        }
    }

    public static void main(String[] args) throws IOException {
        TCPEchoexchange tcpEchoexchange=new TCPEchoexchange(6666);
        tcpEchoexchange.start();
    }
}

简易的字典

import java.io.IOException;
import java.util.HashMap;

public class TCPEchoMapsever  extends TCPEchoSever{
    HashMap<String,String> map;
    public TCPEchoMapsever(int pase) throws IOException {
        super(pase);
        map=new HashMap<>();
        map.put("狗","dog");
        map.put("猫","cat");
        map.put("鸡","chicken");
        map.put("猪","pig");
    }

    @Override
    protected String Calculation(String request) {
        String key= map.getOrDefault(request,"没有找到");
        return key;
    }

    public static void main(String[] args) throws IOException {
        TCPEchoMapsever tcpEchoMapsever=new TCPEchoMapsever(8888);
        tcpEchoMapsever.start();
    }
}

多线程实现

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class TCPchoThread extends TCPEchoSever{

    public TCPchoThread(int pase) throws IOException {
        super(pase);
    }

    @Override
    public void start() throws IOException {
        System.out.println("服务端已启动");
        while (true){
            Socket client=socket.accept();
            Thread th = new Thread (()->{
                try {
                    reviceports(client);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
            th.start();
        }
    }
    public static void main(String[] args) throws IOException {
        TCPchoThread tcPchoThread=new TCPchoThread(9999);
        tcPchoThread.start();
    
}

线程池实现

import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TCPEchoPoolthread extends TCPEchoSever {

    public TCPEchoPoolthread(int pase) throws IOException {
        super(pase);
    }
    @Override
    public void start() throws IOException {
        ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(4,10,1,TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2));
        System.out.println("服务端已启动,等待客服端连接");
        while (true){
            Socket client=socket.accept();
            threadPoolExecutor.submit(()->{
                try {
                    reviceports(client);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
            }
        }
    public static void main(String[] args) throws IOException {
        TCPEchoPoolthread tcpEchoPoolthread=new TCPEchoPoolthread(7777);
        tcpEchoPoolthread.start();
    }
}

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值