Java架构学习(八)Socket&TCP&UDP

Socket网络通讯基础

怎么区分客户端与服务器端?
谁发起的请求,谁就为客户端,谁接受请求谁为服务端。

一、Socket入门

Socket就是为网络服务提供的一种机制

通讯的两端都有Socket
网络通讯其实就是Socket间通讯IO传输。

二、网络模型

应用层:
传输层:
网络层:
链路层:

任何计算机语言通讯,底层都使用socket技术。
Socket计数遵循一个规范:二进制+IP+端口号


Socket分为非常核心的两个:TCP UDP

三、UDP&TCP

1、udp:面向无连接--不会建立连接、数据传输64k 是不可靠协议
2、tcp:面向连接协议、三次握手、以字节流传输,UPD效率比TCP高,
   tcp协议比udp靠谱

使用udp实现传输数据

先写服务器端。
案例:
package com.leeue.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * 
 * @classDesc: 功能描述:(使用udp 来传输数据)
 * @author:<a href="leeue@foxmail.com">李月</a>
 * @Version:v1.0
 * @createTime:2018年7月27日 上午11:14:46
 */

class UdpServer {//服务器端类

    public static void main(String[] args) throws IOException {
        //第一步肯定是拿到 ip+端口号
        System.out.println("udp服务器已经启动...");
        //创建服务器端 端口号,不用传递ip地址就是因为 默认是本机地址 
        DatagramSocket datagramSocket = new DatagramSocket(8080);
        //服务器端接受客户端1024个字节
        byte[] bytes = new byte[1024];

        //定义数据包
        DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
        //接受客户端请求,将数据封装给数据包,如果客户端不往服务器端发送请求就会一直阻塞
        datagramSocket.receive(datagramPacket);
        System.out.println("来源IP地址:"+datagramPacket.getAddress()+"端口号:"+datagramPacket.getPort());

        String string = new String(datagramPacket.getData(),0,datagramPacket.getLength());
        System.out.println(string);
        //关闭socket连接
        datagramSocket.close();

    }
}

public class UdpClient {
    public static void main(String[] args) throws IOException {
          System.out.println("upd客户端启动连接...");
          //不传入端口号 作用客户端 创建一个socket客户端
          DatagramSocket ds = new DatagramSocket();

          String string="蚂蚁课堂";
          byte[] strBytes = string.getBytes();
          DatagramPacket dp = new DatagramPacket(strBytes, strBytes.length,InetAddress.getByName("127.0.0.1"),8080);
          ds.send(dp);
          ds.close();
    }
}

四、TCP的三次握手

TCP协议采用三次握手成功之后,才开始进行数据传输。
在最后一次就会进行四次挥手,效率比UDP效率要慢。


在传输数据之前要经过三次握手确认,报文确认。

这里写图片描述

整个握手的时候是通过 TCP协议的。


四次分手也是类似这种。

TCP如果要关闭的话,两边都会进行关闭。

这里写图片描述


案例

五、TCP协议发送客户端与服务端

案例:
package com.leeue.tcp;

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

/**
 * 
 * @classDesc: 功能描述:(TCP连接)
 * @author:<a href="leeue@foxmail.com">李月</a>
 * @Version:v1.0
 * @createTime:2018年7月27日 下午2:48:59
 */

class tcpServer{
    public static void main(String[] args) throws IOException {
        System.out.println("tcp协议服务器启动了");
        ServerSocket serverSocket = new ServerSocket(8080);
        //接受客户端请求 阻塞功能
        Socket accept = serverSocket.accept();

        InputStream inputStream = accept.getInputStream();

        //将字节流转换程String 类型

        byte[] bytes = new byte[1024];
        int len = inputStream.read(bytes);
        String result = new String(bytes, 0, len);
        System.out.println("服务器端接受客户端内容:"+result);
        serverSocket.close();


    }
}
public class TcpDemo {
    public static void main(String[] args) throws IOException {
        System.out.println("socket tcp 客户端启动...");
        //创建socket客户端
        Socket socket = new Socket("127.0.0.1", 8080);

        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("我是哈哈哈哈".getBytes());
        socket.close();
    }
}

Http协议底层就是使用TCP协议来进行传输的

怎么解决 tcp协议同时支持多个请求?


使用线程池,支持多个线程同时支持多个请求。  使用线程池来做伪异步的效果,
节约内存,



第一种方法:只能是一个线程在运行使用while循环来
package com.leeue.tcp;

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

/**
 * 
 * @classDesc: 功能描述:(TCP连接)
 * @author:<a href="leeue@foxmail.com">李月</a>
 * @Version:v1.0
 * @createTime:2018年7月27日 下午2:48:59
 */

class tcpServer{
    public static void main(String[] args) throws IOException {
        System.out.println("tcp协议服务器启动了");
        ServerSocket serverSocket = new ServerSocket(8080);

        try {
            while(true) {
                //接受客户端请求 阻塞功能
                Socket accept = serverSocket.accept();

                InputStream inputStream = accept.getInputStream();

                //将字节流转换程String 类型

                byte[] bytes = new byte[1024];
                int len = inputStream.read(bytes);
                String result = new String(bytes, 0, len);
                System.out.println("服务器端接受客户端内容:"+result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            serverSocket.close();
        }



    }
}
public class TcpDemo {
    public static void main(String[] args) throws IOException {
        System.out.println("socket tcp 客户端启动...");
        //创建socket客户端
        Socket socket = new Socket("127.0.0.1", 8080);

        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("我是哈哈哈哈".getBytes());
        socket.close();
    }
}
第二种方法: 使用多线程优化的版本
package com.leeue.tcp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 
 * @classDesc: 功能描述:(使用多线程支持多个连接访问)
 * @author:<a href="leeue@foxmail.com">李月</a>
 * @Version:v1.0
 * @createTime:2018年7月27日 下午2:48:59
 */

class tcpServer {
    public static void main(String[] args) throws IOException {
        System.out.println("tcp协议服务器启动了");
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
        // 创建服务器端连
        ServerSocket serverSocket = new ServerSocket(8080);
        try {
            while (true) {
                // 接受客户端请求 阻塞功能
                Socket accept = serverSocket.accept();

                newCachedThreadPool.execute(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            InputStream inputStream = accept.getInputStream();

                            // 将字节流转换程String 类型

                            byte[] bytes = new byte[1024];
                            int len = inputStream.read(bytes);
                            String result = new String(bytes, 0, len);
                            System.out.println("服务器端接受客户端内容:" + result);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                });

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            serverSocket.close();
        }

    }
}

public class TcpDemo {
    public static void main(String[] args) throws IOException {
        System.out.println("socket tcp 客户端启动...");
        // 创建socket客户端
        Socket socket = new Socket("127.0.0.1", 8080);

        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("我是哈哈哈哈".getBytes());
        socket.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值