TCP、UDP、Socket

  • 网络通讯的三要素:
    • 一、 IP
  • IP地址

Internet上的每台主机(Host)都有一个唯一的IP地址。IP地址的长度为32位,分为4段,每段8位,用十进制数字表示,每段数字范围为0~255,段与段之间用句点隔开。例如159.226.1.1。(四个字节)

  • IP地址类别
    IP地址是由网络号和主机号组成
    IP地址是由网络号和主机号组成
    A类地址:8位网络位,24位主机位 政府单位
    B类地址:16位网络位,16位主机位 事业单位(学校、银行..)
    C类地址:24位网络位,8位主机位 私人使用..
  • 特殊的IP地址
    127.0.0.1 表示 本机回环地址
    • 二、 Port端口号
      • Port地址

如果把IP地址比作一间房子 ,端口就是出入这间房子的门。真正的房子只有几个门,但是一个IP地址的端口 可以有65536(即:2^16)个之多!端口是通过端口号来标记的,端口号只有整数,范围是从0 到65535(2^16-1)

 - Port分类(0~65535)

公认端口(WellKnownPorts):从0到1023,它们紧密绑定(binding)于一些服务。
注册端口(RegisteredPorts):从1024到49151。它们松散地绑定于一些服务。
动态和/或私有端口(Dynamicand/orPrivatePorts):从49152到65535

  • 常用端口
    21 ---> FTP
    80 ---> HTTP
    443 ---> HTTPS
    • 三、协议
  • TCP:

TransmissionControl Protocol 传输控制协议TCP是一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transportlayer)通信协议。
特点:
面向连接的协议,数据传输必须要建立连接,所以在TCP中需要连接时间。
传输数据大小限制,一旦连接建立,双方可以按统一的格式传输大的数据。
一个可靠的协议,确保接收方完全正确地获取发送方所发送的全部数据。

  • UDP:

User Datagram Protocol的简称,中文名是用户数据包协议,是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
特点:
每个数据报中都给出了完整的地址信息,因此无需要建立发送方和接收方的连接。
UDP传输数据时是有大小限制的,每个被传输的数据报必须限定在64KB之内。
UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。

  • TCP和UDP
    • UDP通讯协议的特点:
      将数据封装为数据包,面向无连接。
      每个数据包大小限制在64K中
      因为无连接,所以不可靠
      因为不需要建立连接,所以速度快
      UDP 通讯是不分服务端与客户端的,只分发送端与接收端。
      比如: 物管的对讲机, QQ聊天、 游戏...
/*
发送端的使用步骤:
    1. 建立udp的服务。
    2. 准备数据,把数据封装到数据包中发送。 发送端的数据包要带上ip地址与端口号。
    3. 调用udp的服务,发送数据。
    4. 关闭资源。
*/
// 发送方
public class Sender {

    public static void main(String[] args) throws IOException {
        // 创建UDP服务
        DatagramSocket socket = new DatagramSocket();

        // 准备数据,把数据封装到数据包
        String dataStr = "您好,请查收信息哦";

        // 创建一个数据包
        DatagramPacket packet = new DatagramPacket(dataStr.getBytes(), dataStr.getBytes().length, InetAddress.getLocalHost(), 60900);
        
        // 调用UDP服务发送数据包
        socket.send(packet);

        // 关闭UDP服务
        socket.close();
    }
}

//接收端
/*
 接收端的使用步骤
    1. 建立udp的服务
    2. 准备空 的数据 包接收数据。
    3. 调用udp的服务接收数据。
    4. 关闭资源
 
 */
public class Revice {

    public static void main(String[] args) throws IOException {
        
        // 创建UDP服务
        DatagramSocket socket = new DatagramSocket(60900);
        
        // 准备空的数据包接收数据
        byte[] buff = new byte[1024];
        
        DatagramPacket packet = new DatagramPacket(buff, buff.length);
        
        // 调用UDP服务接收数据
        socket.receive(packet);
        System.out.println("接收到数据:" + new String(buff, 0, packet.getLength()));
        socket.close();
    }
}
  • TCP通讯协议特点:
    TCP是基于IO流进行数据 的传输 的,面向连接。
    TCP进行数据传输的时候是没有大小限制的。
    TCP是面向连接,通过三次握手的机制保证数据的完整性。 可靠协议。
    TCP是面向连接的,所以速度慢。
    TCP通讯是区分客户端与服务端 的。
    比如: 打电话、 QQ的文件传输、 迅雷下载....

TCP协议下的Socket:
Socket(客户端) , TCP的客户端一旦启动马上要与服务端进行连接。
ServerSocket(服务端类)

/*
tcp的客户端使用步骤:
1. 建立tcp的客户端服务。
2. 获取到对应的流对象。
3.写出或读取数据
4. 关闭资源。

*/
// TCP的客户端
public class ChatClient {

    public static void main(String[] args) {
        
        try {
            // 创建TCP服务
            Socket socket = new Socket(InetAddress.getLocalHost(), 20000);
            
            // 获取socket的输出流对象
            OutputStream outputStream = socket.getOutputStream();
            
            // 利用输出流对象写入数据
            outputStream.write("客户端说:您好,我是客户端".getBytes()); 
            
            // 获取到输入流对象,读取服务端返回的数据
            InputStream inputStream = socket.getInputStream();
            byte[] buffer = new byte[1024];
            int length = inputStream.read(buffer);
            System.out.println("服务端说:" + new String(buffer, 0, length));
            
            // 关闭客户端
            outputStream.close();
            
        } catch (IOException e) {
            throw new RuntimeException(e);
        
        }   
    }
}

// TCP服务端
public class ChatService {

    public static void main(String[] args) {
        
        try {
            // 建立TCP的服务端,并监听一个端口
            ServerSocket serverSocket = new ServerSocket(20000);
            
            // 接受客户端的连接 该方法也是一个阻塞型的方法,没有客户端与其连接时,会一直等待下去。
            Socket socket = serverSocket.accept();
            
            // 获取输入流对象,读取客户端发送的数据
            InputStream inputStream = socket.getInputStream();
            
            byte[] buffer = new byte[1024];
            int length = 0;
            length = inputStream.read(buffer);
            System.out.println("客户端说:" + new String(buffer, 0, length));
            
            // 获取socket的输出流对象,向客户端发送数据
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write("服务端说:您好我是服务端".getBytes());
            
            // 关闭服务端
            serverSocket.close();
            
        } catch (IOException e) {
            throw new  RuntimeException(e);
        }
        
    }
}
  • Socket
    • 套接字(socket)概念

套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远程进程的协议端口。
应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

  • 建立socket连接
    建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。
    套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

    • 服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
    • 客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
    • 连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户 端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
  • SOCKET连接与TCP连接
    创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。

  • Socket连接与HTTP连接
    由于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。
    而HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。
    很 多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数据传送给客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可以 保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户端。

  • Scoket连接和HTTP连接的区别:
    HTTP协议是基于TCP连接的,是应用层协议,主要解决如何包装数据。Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
    HTTP连接:短连接,客户端向服务器发送一次请求,服务器响应后连接断开,节省资源。服务器不能主动给客户端响应(除非采用HTTP长连接技术)
    Socket连接:长连接,客户端跟服务器端直接使用Socket进行连接,没有规定连接后断开,因此客户端和服务器段保持连接通道,双方可以主动发送数据,一般多用于游戏.Socket默认连接超时时间是30秒,默认大小是8K(理解为一个数据包大小)。

// 练习1: 使用TCP实现客户端与服务端一问一答聊天
// 客户端类
public class Client {

    public static void main(String[] args) throws IOException {
        
        // 建立TCP的客户端服务
        Socket socket = new Socket(InetAddress.getLocalHost(), 20000);
        
        // 获取socket的输出流对象
        OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
        // 获取socket的输入流对象
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        
        // 获取键盘的输入流对象,读取数据
        BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in));
        
        // 不断的读取键盘录入的数据然后把数据输出
        String lineStr = null;
        while ((lineStr = keyReader.readLine()) != null) {
            System.out.println();
            writer.write(lineStr + "\r");
            // 刷新数据
            writer.flush();
            
            // 读取服务器返回的数据
            lineStr = reader.readLine();
            System.out.println("服务器返回的数据是:" + lineStr);
        }
        
        // 关闭socket
        socket.close();
    }
}

// 服务端类
public class Service {

    public static void main(String[] args) throws IOException {
        
        // 建立tcp的服务端
        ServerSocket serverSocket = new ServerSocket(20000);
        
        // 接收服务端的连接,并获取一个socket
        Socket socket = serverSocket.accept();
        
        // 获取到socket的输入流对象
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        
        // 获取到socket的输出流对象
        OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
        
        // 获取键盘的输入流对象
        BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in));
        
        // 读取客户端的数据
        String lineStr = null;
        while ((lineStr = reader.readLine()) != null) {
            System.out.println("服务器接收到的数据:" + lineStr);
            
            System.out.println("请输入回复客户端的数据");
            
            lineStr = keyReader.readLine();
            
            writer.write(lineStr + "\r");
            writer.flush();
        }
        
        // 关闭资源
        serverSocket.close();
    }
}
// 练习2:编写一个服务器,可以让多个客户端可以下载图片
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;

// 练习:编写一个服务器,可以让多个客户端下载图片

// 模拟服务器类
public class ImageService extends Thread {

    Socket socket;
    // 使用该集合是用于存储ip地址的,由于重复元素不会被添加,间接记录下载的人数
    HashSet< String> ipSet = new HashSet<String>();
    
    @Override
    public void run() {
        try {
            // 获取socke的输出流对象
            OutputStream outputStream = socket.getOutputStream();
            // 获取图片的输入流对象
            FileInputStream fileInputStream = new FileInputStream("/Users/mofeini/Desktop/to/4.jpg");
            // 读取图片,把数据写入到指定路径
            byte[] buffer = new byte[1024];
            int length = 0;
            while ((length = fileInputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, length);
            }
            
            String ip = socket.getInetAddress().getHostAddress();
            if(ipSet.add(ip)) {
                System.out.println("第" + ipSet.size() + "下载了图片" );
            }
            
            // 关闭资源
            fileInputStream.close();
            socket.close();
            
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
    
    public ImageService(Socket socket) {
        this.socket = socket;
    }
    
    public static void main(String[] args) throws IOException {
        
        // 建立tcp连接,并监听端口
        ServerSocket serverSocket = new ServerSocket(20002);
        
        while (true) {
            // 确定连接
            Socket socket = serviceSocket.accept();
            new ImageService(socket).start();
        }
        
        
        
    }
}

// 下载图片的客户端
public class ImageClient {

    public static void main(String[] args) throws IOException {
        // 建立tcp服务
        Socket socket = new Socket(InetAddress.getLocalHost(), 20002);
        
        // 获取socket的输入流对象
        InputStream inputStream = socket.getInputStream();
        // 获取文件的输出流对象
        FileOutputStream fileOutputStream = new FileOutputStream("/Users/mofeini/Desktop/to/download.jpg");
        
        // 边读取图片,边下载图片
        byte[] buffer = new byte[1024];
        int length = 0;
        while ((length = inputStream.read(buffer)) != -1) {
            fileOutputStream.write(buffer, 0, length);
        }
        
        // 关闭资源
        fileOutputStream.close();
        socket.close();
    }
    
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容