首页 > 技术文章 > socket的TCP的三次握手/四次挥手

l919310075 2017-08-10 17:30 原文

第一次握手:客户端尝试连接服务器,向服务器发送syn包(同步序列编号Synchronize Sequence Numbers),syn=j,客户端进入SYN_SEND状态等待服务器确认

第二次握手:服务器接收客户端syn包并确认(ack=j+1),同时向客户端发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态

第三次握手:第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手

某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M;

另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;

一段时间之后,接收到文件结束符的应用进程调用close关闭它的socket。这导致它的TCP也发送一个FIN N;

接收到这个FIN的源发送端TCP对它进行确认。

另外服务端和客户端的简单实例如下:

服务器端:

 public static void  main(String[] args)  {
        //SendOvertimeMessage sendOvertimeMessage = new SendOvertimeMessage();
        //sendOvertimeMessage.sendOverTimeMessageReq();
        //获取本机的InetAddress实例
        try {
            //获取本机的InetAddress实例
            InetAddress address =InetAddress.getByName("15.2.19.150");
            System.out.println(address.getCanonicalHostName());;//获取计算机名
            System.out.println(address.getHostAddress());//获取IP地址
            byte[] bytes = address.getAddress();//获取字节数组形式的IP地址,以点分隔的四部分

//获取其他主机的InetAddress实例
//            InetAddress address2 =InetAddress.getByName("其他主机名");
//            InetAddress address3 =InetAddress.getByName("IP地址");
            //使用URL读取网页内容
//创建一个URL实例
//            URL url =new URL("http://www.baidu.com");
//            InputStream is = url.openStream();//通过openStream方法获取资源的字节输入流
//            InputStreamReader isr =new InputStreamReader(is,"UTF-8");//将字节输入流转换为字符输入流,如果不指定编码,中文可能会出现乱码
//            BufferedReader br =new BufferedReader(isr);//为字符输入流添加缓冲,提高读取效率
//            String data = br.readLine();//读取数据
//            while(data!=null){
//                System.out.println(data);//输出数据
//                data = br.readLine();
//            }
//           // System.out.println(data);
//            br.close();
//            isr.close();
//            is.close();
            /**
             * 基于TCP协议的Socket通信,实现用户登录,服务端
             */
//1、创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
//            ServerSocket serverSocket =new ServerSocket(10062);//1024-65535的某个端口
////2、调用accept()方法开始监听,等待客户端的连接
//            Socket socket = serverSocket.accept();
////3、获取输入流,并读取客户端信息
//            InputStream is = socket.getInputStream();
//            InputStreamReader isr =new InputStreamReader(is);
//            BufferedReader br =new BufferedReader(isr);
//            String info =null;
//            while((info=br.readLine())!=null){
//                System.out.println("我是服务器,客户端说:"+info);
//            }
//            socket.shutdownInput();//关闭输入流
////4、获取输出流,响应客户端的请求
//            OutputStream os = socket.getOutputStream();
//            PrintWriter pw = new PrintWriter(os);
//            pw.write("欢迎您!");
//            pw.flush();
//
//
////5、关闭资源
//            pw.close();
//            os.close();
//            br.close();
//            isr.close();
//            is.close();
//            socket.close();
//            serverSocket.close();
        }catch (Exception ex){
            ex.printStackTrace();
        }

    }

客户端:

public static void main(String[] args){
        //客户端
//1、创建客户端Socket,指定服务器地址和端口
        Socket socket = null;
        try {
            socket = new Socket("localhost",10062);
            //2、获取输出流,向服务器端发送信息
            OutputStream os = socket.getOutputStream();//字节输出流
            PrintWriter pw =new PrintWriter(os);//将输出流包装成打印流
            pw.write("用户名:admin;密码:123");
            pw.flush();
            socket.shutdownOutput();
//3、获取输入流,并读取服务器端的响应信息
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String info = null;
            while((info=br.readLine())!= null){
                System.out.println("我是客户端,服务器说:"+info);
            }

//4、关闭资源
            br.close();
            is.close();
            pw.close();
            os.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 

推荐阅读