基于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();  
        }  
    }  

}  
posted @ 2017-11-29 21:12  Philtell  阅读(118)  评论(0)    收藏  举报