• 基于Socket编程,模拟TCP部分协议字段编程


    注意:先启动服务端,再运行客户端
    Client.java 客户端

    package sdut.ligong.demo;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintStream;
    import java.net.Socket;
    import java.net.SocketTimeoutException;
    
    /**
     * 1001 建立连接请求
     * 
     * 1002 确认请求 1003 开始发送信息
     * 
     * 1004 断开连接请求
     * 
     * @author Lenovo
     *
     */
    public class Client1 {
    
        /**
         * 参考TCP报文首部格式
         * 
         * 1.源端口和目的端口 各 占2个字节 2序号 占 4 字节 3确认号 占4字节 4数据偏移 占4位 5保留 占6位 6紧急 URG
         * 为1表示紧急指针字段有效 7确认 ACK 为1表示有效 8推送 PSH 9复位RST 10同步SYN 11终止FIN 12窗口 13检验和
         * 14紧急指针 15选项
         */
    
        // 自定义报文首部格式为 确认号+报文长度+尾部(占一个字节,用于标注存储报文长度的位数)
    
        public static int ESTABLISH_CONNECTION = 1001; // 建立连接
    
        public static int CONFIRM_CONNECTION = 1002; // 确认连接
    
        public static int SEND_INFORMATION = 1003; // 发送报文
    
        public static int TERMINATE_CONNECTION = 1004; // 关闭连接
    
        public static int MESSAGE_LENGTH = 0; // 发送信息的长度
    
        public static int LengthBit = 0;//长度位数
    
        private static String content = null;
    
        public static void main(String[] args) throws IOException {
    
            // 客户端请求与本机在20006端口建立TCP连接
            Socket client = new Socket("127.0.0.1", 20006);
    
            client.setSoTimeout(10000);
    
            // 获取键盘输入
            BufferedReader input = new BufferedReader(new InputStreamReader(
                    System.in));
    
            // 获取Socket的输出流,用来发送数据到服务端
            PrintStream out = new PrintStream(client.getOutputStream());
    
            // 获取Socket的输入流,用来接收从服务端发送过来的数据
            BufferedReader buf = new BufferedReader(new InputStreamReader(
                    client.getInputStream()));
    
            boolean flag = true;
    
            while (flag) {
    
                System.out.print("请输入信息:");
    
                content = input.readLine();
    
                System.out.println("content is the "+content);
    
                System.out.println("开始发送连接请求");
    
    
                MESSAGE_LENGTH =  6;
    
                // 发送1001 请求连接
                out.println(ESTABLISH_CONNECTION + "" + MESSAGE_LENGTH+""+1);
    
                // 发送数据到服务端
    
                if ("bye".equals(content)) {
                    flag = false;
                } else {
                    try {
                        // 从服务器端接收数据有个时间限制(系统自设,也可以自己设置),超过了这个时间,便会抛出该异常
                        String echo = buf.readLine();
    
                        if (echo.contains("1002")) {
    
                            System.out.println("请求被确认");
    
                            System.out.println("准备发送信息!");
    
                            MESSAGE_LENGTH = 4 + content.length() + 1;
    
                            int m = MESSAGE_LENGTH;
                            if(m+1==10){  //如果输入内容长度为4加上固定长度5,加上长度空间占位1,则报文总长度为10,长度空间需要再增一位
                                m=10;
                            }
    
                            boolean t = true;
                            LengthBit = 0;
                            while(t){
                                if(m==0){
                                    t = false;
                                }else {
                                    m=m/10;
                                    LengthBit++;
                                }
                            }
    
                            MESSAGE_LENGTH+=LengthBit;//加上报文长度占的内存空间
    
                //发送报文
                            out.println(SEND_INFORMATION +""+MESSAGE_LENGTH +""+content+""+LengthBit);
    
    
                            String echo2 = buf.readLine();
    //解析报文
                            int num = Integer.parseInt(echo2.substring(echo2.length()-1));
    
                            System.out.println(echo2.substring(4+num, echo2.length()-1));
                            System.out.println(echo2);
    
                        } else {
    
                            System.out.println("请求连接被拒绝");
    
                        }
    
                    } catch (SocketTimeoutException e) {
                        System.out.println("超时,无响应");
                    }
                }
            }
            input.close();
            if (client != null) {
                // 如果构造函数建立起了连接,则关闭套接字,如果没有建立起连接,自然不用关闭
                client.close(); // 只关闭socket,其关联的输入输出流也会被关闭
            }
        }
    }
    

    Server1.java

    package sdut.ligong.demo;
    
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class Server1 {  
        public static void main(String[] args) throws Exception{  
            //服务端在20006端口监听客户端请求的TCP连接  
            ServerSocket server = new ServerSocket(20006);  
            Socket client = null;  
            boolean f = true;  
            while(f){  
                //等待客户端的连接,如果没有获取连接  
                client = server.accept();  
                System.out.println("与客户端连接成功!");  
                //为每个客户端连接开启一个线程  
                new Thread(new ServerThread(client)).start();  
            }  
            server.close();  
        }  
    }  
    

    ServerThread.java

    package sdut.ligong.demo;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.PrintStream;
    import java.net.Socket;
    
    public class ServerThread implements Runnable {  
    
        private Socket client = null;  
        public ServerThread(Socket client){  
            this.client = client;  
        }  
    
        @Override  
        public void run() {  
            try{  
                //获取Socket的输出流,用来向客户端发送数据  
                PrintStream out = new PrintStream(client.getOutputStream());  
                //获取Socket的输入流,用来接收从客户端发送过来的数据  
                BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));  
                boolean flag =true;  
                while(flag){  
                    //接收从客户端发送过来的数据  
                    String str =  buf.readLine();  
                    if(str == null || "".equals(str)){  
                        flag = false;  
                    }else{  
                        if("bye".equals(str)){  
                            flag = false;  
                        }else{  
                            //将接收到的字符串前面加上echo,发送到对应的客户端  
                            if (str.contains("1001")&& (str.charAt(4)+"").equals(str.length()+"")) {//接收到请求连接
                                 out.println("1002");  
                            }else{
                                int  endStart = Integer.parseInt(str.substring(str.length()-1));
                                if (str.contains("1003") && str.length()==Integer.parseInt(str.substring(4,4+endStart))) {
    
                                    StringBuffer sb = new StringBuffer(str);
                                    out.println(new String(sb.insert(4+endStart, "服务器端回应")));
                                } else {
                                    out.print("请求失败");
                                }
                            }
    
                        }  
                    }  
                }  
                out.close();  
                client.close();  
            }catch(Exception e){  
                e.printStackTrace();  
            }  
        }  
    
    }  
    
  • 相关阅读:
    02-vue过滤器和键盘修饰符
    01-vue指令
    webpack
    笔记:随机生成数、字符串
    笔记:long、longlong、int、float、NSString相互转换
    关于NSStringFromClass的一点见解
    iOS中UITextField常用设置和方法
    iOS 倒计时的一种实现
    iOS UITextField的代理<UITextFieldDelegate>的几点笔记
    iOS 单例模式简单实例
  • 原文地址:https://www.cnblogs.com/CCCrunner/p/11781753.html
Copyright © 2020-2023  润新知