用一张图来认识一下TCP和UDP

TCP点对点的传输方式,保证了数据的可达性;UDP只管发送数据,至于服务端能否接收到数据,不在它的保证范围之内。

下面,我们进入正题。

一、网络架构模型

TCP/IP协议分为分层架构:物理层、数据链路层、网络层、传输层、应用层。

应用层:能被用户感知到的一层,如浏览器的http、https协议,远程连接工具的ftp、ftps协议等。

传输层:两台计算机之间的交互数据传输,就在这一层完成,传输层为上层协议提供端到端的可靠和透明的服务。TCP和UDP就是在这一层,是应用层协议的基础。进程的端口号,就是在这一层。

网络层:也就是IP层,两台计算机之间进行通信,先通过IP找到目标计算机,再根据端口号定位到具体的进程,然后进行数据传输。IP协议是internet 的基础。

二、socket编程

socket本质是编程语言的API,在Java中就是具体的类,socket 类对TCP/IP和UDP/IP协议进行了封装,提供一个可以供程序员做开发使用的接口。

TCP和UDP的区别

TCP:

  1. 基于连接,也就是两台计算机进行传输数据之前,必然先进行连接,也就是TCP中的三次握手,建立连接
  2. TCP连接,传输数据没有大小限制,一旦建立连接,可以按照约定的数据格式,传输所需数据。
  3. TCP是一个可靠的协议,它会确保接受双方能够正确完整的接收到对方传输的数据(基于连接,保证了可靠性)。

UDP:

  1. 基于数据包来发送数据,数据包中包括了目标的IP、端口以及所要发送的数据。
  2. 传输数据大小受到了限制,每个数据包都必须小于64k。
  3. UDP是一个不可靠的协议;双方数据传输不需要建立连接,发送方封装好数据后,只管发送,不管接受方能不能接收到数据。

TCP 的三次握手

第一次握手:客户端向服务端发送sny包,包括标记sny=1和数据seq=x,并进入sny_send状态。

第二次握手:服务端接收到客户端的TCP报文,确认客户端发送的数据seq=x没有问题,向客户端返回TCP报文,包括标记sny=1,确认ack=x+1,数据seq=y,并进入sny_recv状态。

第三次握手:客户端接收到服务端返回的TCP报文,确认服务端发送的数据seq=y没有问题,向服务端发送TCP报文,包括标记sny=1,确认ack=y+1, seq=x+1,并进入established状态。

服务端接收到客户端的TCP报文,进入established状态,双方可以进行数据传输。

三、TCP协议实现

socket实现的TCP协议客户端: TcpClient.java

import java.io.*;
import java.net.UnknownHostException;
import java.util.Scanner;
public class TcpClient {private final static String SERVER_IP = "127.0.0.1";private final static int SERVER_PORT = 10888;public static void main(String[] args) throws Exception {TcpClient tcpClient = new TcpClient();Scanner in = new Scanner(System.in);while(true) {String msg = in.next();if("exit".equals(msg)) {break;}tcpClient.startTcpClient(SERVER_IP, SERVER_PORT, msg);}}public void startTcpClient(String ip, int port, String msg) throws Exception {//创建客户端 socket,并连接服务端IP:portSocket socket = new Socket(ip, port);//打开socket数据输出流OutputStream outputStream = socket.getOutputStream();PrintWriter printWriter = new PrintWriter(outputStream);//将数据 写入输出流printWriter.write(msg);//刷新缓冲区,输出缓冲区的数据;如果不刷新,服务端接收到数据printWriter.flush();//关闭socket客户端的输出流//当socket的写操作打开后,会一直阻塞,所以,每次写完数据,需要关闭socket的写操作socket.shutdownOutput();/************* 客户端接受服务器返回的数据 ***************///打开socket输入流InputStream inputStream = socket.getInputStream();//字节流转字符流,并指定编码InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"UTF-8");//字符流封装成缓冲流BufferedReader bufferedReader = new BufferedReader(inputStreamReader);StringBuffer stringBuffer = new StringBuffer();String len = null;while((len = bufferedReader.readLine()) != null) {stringBuffer.append(len);}  System.out.println("接收到客户端返回的数据:" + stringBuffer.toString());//关闭流bufferedReader.close();inputStreamReader.close();inputStream.close();printWriter.close();outputStream.close();      }
}

socket实现的TCP协议服务端:TcpServer.java

import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {public static void main(String[] args) throws Exception {TcpServer tcpServer = new TcpServer();tcpServer.startServer(10888);}public void startServer(int port) throws Exception {//创建一个socket服务端,监听port 端口ServerSocket serverSocket = new ServerSocket(port);System.out.println("TCP服务器启动,并监听端口:" + port);//创建一个连接客户端的socketSocket socket = null;//创建一个循环,web项目以监听实现int count = 0;while(true){//监听客户端,等待客户端连接socket = serverSocket.accept();System.out.println("第" + count + "个客户端请求开始处理!");//创建一个线程,专门处理当前客户端的请求,以便继续处理其他客户端请求,避免阻塞TcpServerThread tcpServerThread = new TcpServerThread(socket);Thread thread = new Thread(tcpServerThread);thread.start();count++;}}
}

服务端处理客户端请求的线程: TcpServerThread.java

import java.io.*;
import java.net.Socket;
public class TcpServerThread implements Runnable {private Socket socket;public TcpServerThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {InputStream inputStream = null;InputStreamReader inputStreamReader = null;BufferedReader bufferedReader = null;PrintWriter printWriter = null;OutputStream outputStream = null;try {//获取socket 字节输入流inputStream = socket.getInputStream();//字节流转字符流,指定编码inputStreamReader = new InputStreamReader(inputStream,"utf-8");//字符流封装成缓冲字符流bufferedReader = new BufferedReader(inputStreamReader);StringBuffer stringBuffer = new StringBuffer();String len = null;while((len = bufferedReader.readLine()) != null){stringBuffer.append(len);}System.out.println("客户端的地址:" + socket.getInetAddress() + ",客户端的端口:" + socket.getPort() + "接收到客户端的数据为:" + stringBuffer.toString());/***************   服务端返回数据给客户端  ***************/outputStream = socket.getOutputStream();printWriter = new PrintWriter(outputStream);printWriter.write("客户端你好,我接受到了你的数据:" + stringBuffer.toString());//刷新缓冲区,输出缓冲区的数据,如果不刷新,客户端接受不到数据printWriter.flush();//当socket的写操作打开后,会一直阻塞,所以,每次写完数据,需要关闭socket的写操作socket.shutdownOutput();} catch (IOException e) {e.printStackTrace();}finally {try {printWriter.close();outputStream.close();bufferedReader.close();inputStreamReader.close();inputStream.close();} catch (IOException e) {e.printStackTrace();}}}
}

先启动服务端,再启动客户端,演示动画:

四、UDP协议的实现

UDP客户端:UdpClient.java

import java.net.*;
import java.util.Scanner;
public class UdpClient {public final static String SERVER_IP = "127.0.0.1";public final static int SERVER_PORT = 10999;public final static int BYTE_LENGTH = 1024;public static void main(String[] args) throws Exception {UdpClient udpClient = new UdpClient();Scanner in = new Scanner(System.in);while(true) {String msg = in.next();if("exit".equals(msg)) {break;}udpClient.startUdpClient(SERVER_IP, SERVER_PORT, msg);}}public void startUdpClient(String ip, int port, String msg) throws Exception {//创建一个UDP的客户端DatagramSocket datagramSocket = new DatagramSocket();//发送给服务端的数据byte[] bytes = msg.getBytes("UTF-8");//封装数据包,包括数据、服务端IP、服务端端口DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(ip), port);//发送数据datagramSocket.send(datagramPacket);/*********** 接收服务端发来的消息, 也可以像服务端开启新的线程 ************///用来接受服务端发来的数据byte[] receiveData = new byte[BYTE_LENGTH];//封装数据报,用来接收数据DatagramPacket receiveDataPacket = new DatagramPacket(receiveData, receiveData.length);//接受数据,阻塞,直到有数据发来datagramSocket.receive(receiveDataPacket);String serverSendData = new String(receiveDataPacket.getData(),0,receiveDataPacket.getLength(),"UTF-8");System.out.println("服务端返回的数据:" + serverSendData + ",服务端IP:" + receiveDataPacket.getAddress() + ",服务端端口:" + receiveDataPacket.getPort());}
}

UDP服务端:UdpServer.java

import java.net.*;
public class UdpServer {public final static int SERVER_PORT = 10999;public final static int BYTE_LENGTH = 1024;public static void main(String[] args) throws Exception {UdpServer udpServer = new UdpServer();udpServer.startUdpServer(SERVER_PORT);}public void startUdpServer(int port) throws Exception {// 创建UDP服务端,监听port端口DatagramSocket datagramSocket = new DatagramSocket(port);//创建一个字节数组,用来接受客户端发来的数据byte[] bytes = new byte[BYTE_LENGTH];//创建数据报,用来接收数据DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);System.out.println("开启UDP服务端,并监听端口:" + port);//创建一个循环,接收和处理客户端发送的数据while (true){//接收客户端发送的数据,阻塞,直到有客户端发送数据datagramSocket.receive(datagramPacket);//获取接收到的数据String receiveData = new String(datagramPacket.getData(),0,datagramPacket.getLength(),"UTF-8");//获取客户端IPInetAddress clientIP = datagramPacket.getAddress();//获取客户端端口号int clientPort = datagramPacket.getPort();System.out.println("接收到客户端发送的数据:" + receiveData + ",客户端IP:" + clientIP + ",客户端端口:" + clientPort);//服务端返回给客户端的数据byte[] sendData = ("客户端你好!"+System.currentTimeMillis()).getBytes("UTF-8");//将数据、客户端IP、客户端端口封装进数据报DatagramPacket里面DatagramPacket sendDataPacket = new DatagramPacket(sendData, sendData.length, clientIP, clientPort);//发送数据datagramSocket.send(sendDataPacket);}}
}

先启动服务端,再启动客户端,演示动画:

Java socket编程详解,TCPUDP实现相关推荐

  1. Java Socket编程详解

    Java Socket编程是Java网络编程很重要的内容,现参考了许多资料,总结如下: 1. Java网络编程原理+Socket编程 http://www.cnblogs.com/linzheng/a ...

  2. java IO编程详解

    java IO编程详解 一.Socket 1. Sock概述 Socket,套接字就是两台主机之间逻辑连接的端点.TCP/IP协议是传输层协议,主要解决数据如何在网络中传输,而HTTP协议是应用层协议 ...

  3. PHP SOCKET编程详解

    这篇文章主要介绍了PHP SOCKET编程详解,需要的朋友可以参考下 1. 预备知识 一直以来很少看到有多少人使用php的socket模块来做一些事情,大概大家都把它定位在脚本语言的范畴内吧,但是其实 ...

  4. Linux的SOCKET编程详解

    Linux的SOCKET编程详解 一. 网络中进程之间如何通信 进程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系统 ...

  5. Linux的SOCKET编程详解——非常叼

    http://blog.csdn.net/hguisu/article/details/7445768/ 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] Linux的SOCKE ...

  6. php里面的socket编程,详解PHP Socket 编程过程

    详解PHP Socket 编程过程 作者:PHPYuan 时间:2019-03-13 03:41:20 概述 Socket用于进程间通信.进程间通信通常基于客户端-服务端模型.此时,客户端-服务端是可 ...

  7. Linux的SOCKET编程详解(转载)

    一. 网络中进程之间如何通信 进程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进程之间既互不干扰又协调一致工作,操作系统为进程通信提供了相应设施,如: UN ...

  8. Netty的Socket编程详解-搭建服务端与客户端并进行数据传输

    场景 Netty在IDEA中搭建HelloWorld服务端并对Netty执行流程与重要组件进行介绍: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article ...

  9. C# Socket 编程详解

    Microsoft.Net Framework为应用程序访问Internet提供了分层的.可扩展的以及受管辖的网络服务,其名字空间System.Net和 System.Net.Sockets包含丰富的 ...

  10. Java Socket 参数详解

    Java socket参数选项: TCP_NODELAY:  表示立即发送数据 SO_RESUSEADDR:  表示是否允许重用socket所绑定的本地地址 SO_TIMEOUT :  表示接收数据时 ...

最新文章

  1. python笔记基础-Python基础知识
  2. python映射类型-什么是python中唯一的映射类型
  3. webform(九)——JQuery基础(选择器、事件、DOM操作)
  4. java treeset 红黑树_【数据结构】红黑树与跳表-(SortSet)-(TreeMap)-(TreeSet)
  5. 【NLP】CS224N课程笔记|词向量I: 简介, SVD和Word2Vec
  6. 基于ZooKeeper实现HA高可用性以及自动主备切换
  7. 信息学奥赛一本通(1206:放苹果)
  8. DEM数据获取方法与采样基础理论
  9. R语言_根据马科维茨投资组合理论画出最优投资组合线
  10. swift 框架大全
  11. pwm一个时间单位_时间的换算单位是怎么换算的啊,秒,毫秒,微妙,纳秒等
  12. 【408数据结构】备考常见必会算法图鉴
  13. mac 打字卡顿的解决方法
  14. 沪牌学院-沪拍拍课堂1: 估价策略
  15. vue + element 表格数据导出为excel表格
  16. FJUT ACM 1212 集训队的药药切克闹
  17. mi8se android9,小米小米 8SE(安卓9.0)刷机解锁教程,看教程秒懂刷机,亲测可用...
  18. Hexo阶段三 -- 将Hexo部署到github
  19. AI 以 5:0 比分击败美顶级飞行员;经典对抗攻击 Deepfool 原理详解
  20. Python基础知识(Python的简介、Python环境的安装、集成开发环境Pycharm的安装)

热门文章

  1. spring和jump区别_JUMP与 SKIP 的区别
  2. magicbookpro做php开发,荣耀MagicBook Pro锐龙版,一款为大学生量身打造的笔记本
  3. 2022 Google IO大会新技术
  4. 前端人脸识别框架tracking.js,解决ios浏览器调摄像头黑屏的问题,兼容pc、安卓、ios。
  5. 人民币大写数字 C++
  6. 普通文本与富文本,超文本之间的区别
  7. C++ delete指针需置空
  8. 在word中怎么实现奇数页页眉用本章标题,偶数页用论文标题?
  9. 论文写作-如何设置页眉奇偶页显示不同
  10. 参加第2届全国高校大数据教学研讨会总结