写在前面的废话:马上要找工作了,做了一年的.net ,到要找工作了发现没几个大公司招聘.net工程师,真是坑爹呀。哎,java就java吧,咱从头开始学呗,啥也不说了,玩命撸吧,我真可怜啊。

摘要:

本片记载刚刚学习的网络编程的内容,网络编程也称 Socket 编程 、套接字编程。

什么是Socket?

用于描述ip地址和端口,是一个通信链的Handle。在Internet上的主机一般运行了多个服务软件,同时提供几种服务,每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket就是为了网络编程提供的一种机制,通信的两端都有socket,网络通信其实就是socket间的通信,数据在两个socket之间通过 IO 传输。(摘自黑马视频ppt).

网络通信的三要素:

IP地址:

网络中设备的标识,也可以用主机名识别,但ip地址唯一,主机名不唯一;

端口号:

用于标识进程的逻辑地址,是不同进程的标识;

传输协议:

也即通信的规则,常见的协议由 UDP 协议 和 TCP协议;

UDP协议和TCP协议

(1)UDP

UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据报的方法(百度百科截取)。

百度上讲的有点复杂,不太容易懂,比较通俗的说法就是:UDP协议会把数据打包,然后扔给目标地址,但是这个包能不能扔的到目标机器上,就不管了,udp就只管扔。

所以这种通信协议的优缺点很明显了,优点就是:速度快,效率高;缺点就是:安全性低,容易丢包

(2)TCP

传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议(摘自百度百科)。

通俗说法:tcp协议只在已经确定通信双方都能联系上对方的时候才能进行通信:

     使用tcp协议时要先建立连接;

     建立连接的过程:三次握手,如下图,

UDP协议的简单使用

发送数据流程

  • 创建发送端socket对象;
  • 提供数据,并将数据封装到数据包中;
  • 通过socket服务的发送功能,将数据包发出去;
  • 释放资源;

接收数据流程

  • 创建接收端socket对象;
  • 接收数据;
  • 解析数据;
  • 输出数据;
  • 释放资源;

一个案例:

创建两个控制台程序模拟发送端和接收端,使用udp发送端发送数据,接收端接收数据。

发送端:

SendDemo.java

package com.cherish.Socket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*
* 使用UDP协议发送数据
* 创建发送端Socket对象
* 创建数据并打包
* 发送数据
* 释放资源
*
* DatagramSocket:此类表示用来发送和接受数据,基于UDP协议
*
* DatagramSocket():
* DatagramSocket(int port):
* */
public class SendDemo {
public static void main(String[] args) throws IOException {
//创建发送端Socket对象
DatagramSocket ds = new DatagramSocket();
//创建数据并打包 DatagramPacket表示数据包
//数据 byte[] 设备地址ip 进程的地址 :端口号
String s = "hello udp,i m coming";
byte[] bys = s.getBytes();
int length = bys.length;
InetAddress address = InetAddress.getByName("acer-pc");
int port = 8888;
DatagramPacket dp = new DatagramPacket(bys, length, address,port);
//发送数据
ds.send(dp);
//释放资源
ds.close(); }
}

接收端:

ReceiveDemo.java

package com.cherish.Socket;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress; /*
* 使用UDP协议接受对象:
* 创建接收端Socket对象
* 接受数据
* 解析数据
* 输出数据
* 释放资源
* */
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//创建接收端Socket对象,此处的端口号要跟发送端一致
DatagramSocket ds = new DatagramSocket(8888);
//接收数据
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
System.out.println("接受前");
ds.receive(dp);
System.out.println("接收后");
//解析数据
//InetAddress getAddress()
InetAddress address = dp.getAddress();
//byte[] getData
byte[] data = dp.getData();
int length = dp.getLength();
//输出数据
System.out.println("sender ----"+address.getHostAddress());
System.out.println(new String(data));
} }

运行结果:

说明:

(1)DatagramSocket类

DatagramSocket() :创建实例,通常用于客户端编程,他并没有特定的监听端口,仅仅使用一个临时的。
DatagramSocket(int port) :创建实例,并固定监听Port端口的报文。
DatagramSocket(int port, InetAddress laddr) :这是个非常有用的构建器,当一台机器拥有多于一个IP地址的时候,由它创建的实例仅仅接收来自LocalAddr的报文。
DatagramSocket(SocketAddress bindaddr) :bindaddr对象中指定了端口和地址。

常用方法:

receive(DatagramPacket p) :接收数据报文到p中。receive方法是阻塞的,如果没有接收到数据报包的话就会阻塞在哪里。
send(DatagramPacket p) :发送报文p到目的地。
setSoTimeout(int timeout) :设置超时时间,单位为毫秒。
close() :关闭DatagramSocket。在应用程序退出的时候,通常会主动的释放资源,关闭Socket,但是由于异常的退出可能造成资源无法回收。所以应该在程序完成的时候,主动使用此方法关闭Socket,或在捕获到异常后关闭Socket。

(2)DatagramPacket类

DatagramPacket类用于处理报文,将字节数组、目标地址、目标端口等数据包装成报文或者将报文拆卸成字节数组。

DatagramPacket(byte[] buf, int length, InetAddress addr, int port) :从buf字节数组中取出offset开始的、length长的数据创建数据对象,目标地址是addr,目标端口是port;
DatagramPacket(byte buf[], int offset, int length, SocketAddress address) :从buf字节数组中取出offset开始的、length长的数据创建数据对象,目标地址是address;

常用方法:

getData() byte[] :从实例中取得报文中的字节数组编码。

setData(byte[] buf, int offset, int length): 设置数据报包中的数据内容

TCP协议的简单使用

tcp客户端发送数据流程:

  • 创建发送端Socket对象(创建连接),Tcp的Socket对象与Udp的有所不同,需注意;
  • 获取输出流对象;
  • 发送数据;
  • 释放资源;

tcp服务端接收数据流程:

  • 创建接收端Socket对象;
  • 监听(阻塞):如果建立连接失败,程序会卡在这里,不往下执行;
  • 获取输入流对象;
  • 获取数据;
  • 输出数据;
  • 释放资源;

 案例一:客户端发送数据,服务端接收数据;

ClietDemo.java:

package com.cherish.Socket;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException; /*
* 使用tcp协议发送数据
* 创建发送端Socket对象(创建连接)
* 获取输出流对象
* 发送数据
* 释放资源
* */
public class TcpClientDemo {
public static void main(String[] args) throws IOException{
//创建发送端Socket对象(创建连接)
Socket s = new Socket(InetAddress.getByName("acer-pc"),8886);
//获取输出流对象
OutputStream os = s.getOutputStream();
//发送数据
String str = "hello tcp , i m coming!";
os.write(str.getBytes());
//释放资源
s.close();
}
}

ServerDemo.java: 

package com.cherish.Socket;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket; /*
* 使用tcp协议接受对象
* 创建接收端Socket对象
* 监听(阻塞):如果建立连接失败,程序会卡在这里,不往下执行
* 获取输入流对象
* 获取数据
* 输出数据
* 释放资源
* */
public class TcpServerDemo { public static void main(String[] args) throws IOException {
//创建接收端Socket对象
ServerSocket ss = new ServerSocket(8886);
//监听
Socket s = ss.accept();
//获取输入流对象
InputStream is = s.getInputStream();
//获取数据
byte[] bys = new byte[1024];
int len; //用于存储读到的字节数
len = is.read(bys);
//输出数据
String client = s.getInetAddress().getHostName();
System.out.println(client+"发来的数据");
System.out.println(new String(bys,0,len));
//释放资源
s.close();
//ss.close(); //socket对象一般不释放,因为客户端不止一个,可能有多个客户端会发送数据
}
}

运行结果:

案例二:对案例一进行改进,服务端收到数据后,将数据由小写换成大写,然后返回给客户端:

Client.java:

package com.cherish.Socket.TcpDemo_2;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException; public class Client {
public static void main(String[] args) throws IOException {
//创建发送端socket对象
Socket s = new Socket(InetAddress.getByName("acer-pc"),8866);
//获取输出流对象
OutputStream os = s.getOutputStream();
//写入数据
String str = "hello tcp ,ahahahah!!!";
os.write(str.getBytes());
System.out.println("数据已发送");
//获取输入流对象
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String backStr = new String(bys,0,len);
System.out.println(backStr);
s.close();
}
}

 Server.java:

package com.cherish.Socket.TcpDemo_2;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket; public class Server {
public static void main(String[] args) throws IOException {
//创建服务端接收对象
ServerSocket ss = new ServerSocket(8866);
//监听 来自客户端的连接
Socket s = ss.accept();
//获取输入流对象
InputStream is = s.getInputStream();
//获取数据
byte[] bys = new byte[1024];
int len = is.read(bys);
String str = new String(bys,0,len);
//输出数据
System.out.println(str);
//转换数据
String upperStr = str.toUpperCase();
//获取输出流对象
OutputStream os = s.getOutputStream();
//写入数据到流中
os.write(upperStr.getBytes());
//释放资源
s.close();
}
}

运行结果:

案例三:用tcp模拟一个登录功能,tcp客户端输入用户名和密码,然后发送给服务端,服务端根据输入结果返回登录或失败给客户端;

LoginClient.java:

package com.cherish.Socket.LoginCase;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException; /*
* 模拟用户登录案例
* */
public class LoginClient {
public static void main(String[] args) throws IOException {
//创建客户端socket对象
Socket s = new Socket("acer-pc",8885);
//获取用户名和密码
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入用户名");
String userName = br.readLine();
System.out.println("请输入密码");
String password = br.readLine();
//获取输出流对象
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
//写出数据
out.println(userName);
out.println(password);
//获取输入流对象
BufferedReader serverBr = new BufferedReader(new InputStreamReader(s.getInputStream()));
//获取服务端返回的数据
String backStr = serverBr.readLine();
System.out.println(backStr);
//关闭资源
s.close();
}
}

 LoginServer.java:

package com.cherish.Socket.LoginCase;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket; public class LoginServer {
public static void main(String[] args) throws IOException {
//创建服务端socket对象
ServerSocket ss = new ServerSocket(8885);
//监听
Socket s = ss.accept();
//获取输入流对象
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//获取用户名和密码
String userName = br.readLine();
String password = br.readLine();
//判断用户名和密码是否正确
boolean flag = false;
if (userName.equals("cherish")&&password.equals("123")) {
flag = true;
}
//获取输出流对象
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
//返回判断信息
if (flag) {
System.out.println("成功");
out.println("登录成功");
}else {
out.println("登陆失败");
}
//释放资源
s.close();
//ss.close();//服务端一般不关闭
}
}

运行结果:

结语:本篇博客根据传智播客基础视频整理,记载比较简单,但大致能演示清楚udp和tcp的区别及其用法。个人学习java才不到4天时间,对于java的一些知识点不能讲解的很清楚,因此代码注释写的不是很详细,见谅见谅!哈哈!

本片博客的代码我上传到百度云盘,需要的可自取:

链接:https://pan.baidu.com/s/1-dTfG9GY5MBIAlNJg1v0mw
提取码:3dw6
复制这段内容后打开百度网盘手机App,操作更方便哦

Java基础之UDP协议和TCP协议简介及简单案例的实现的更多相关文章

  1. http协议及http协议和tcp协议的区别

    http是应用层的协议,并且无连接,无状态的协议. http协议的特点: 1.支持c/s模式 2.简单快速:客户端向服务器端传送数据的时候,只需要发送请求方法和路径,请求方法有:post,get,he ...

  2. 了解HTTP协议和TCP协议

    HTTP(超文本传输协议),互联网上应用最为广泛的一种网络协议.所有的www文件都必须遵守这个标准.HTTP是一个客户端和服务端请求和应答的标准(TCP):客户通过浏览器发起一个到服务器上指定端口的H ...

  3. nginx配置http协议和tcp协议配置文件案例

    注意 nginx 1.9版本之后才支持 tcp #user nobody;worker_processes 1; #error_log logs/error.log;#error_log logs/e ...

  4. 网络学习之OSI七层协议和TCP协议

    OSI七层简单介绍 应用层:提供操作系统和应用程序的接口 表示层:表示数据如何加密.如何压缩的 会话层:将不同应用程序数据分离 传输层:提供可靠和不可靠的数据传输和重传.纠错的功能 网络层:提供IP地 ...

  5. 网络协议学习笔记(七)流媒体协议和P2P协议

    概述 上一篇讲解了http和https的协议的相关的知识,现在我们谈一下流媒体协议和P2P协议. 流媒体协议:如何在直播里看到美女帅哥 最近直播比较火,很多人都喜欢看直播,那一个直播系统里面都有哪些组 ...

  6. HTTP协议和SOCKS5协议

    HTTP协议和SOCKS5协议 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们平时上网的时候基本上是离不开浏览器的,尤其是搜索资料的时候,那么这个浏览器是如何工作的呢?用的又是 ...

  7. http协议和https协议

    内容: 1.http协议介绍 2.https协议介绍 3.http协议和https协议对比 1.http协议介绍 (1)http协议是什么 1 一个传输协议,协议就是双方都遵守的规范. 2 为什么叫超 ...

  8. RabbitMQ MQTT协议和AMQP协议

    RabbitMQ MQTT协议和AMQP协议 1        序言... 1 1.1     RabbitMq结构... 1 1.2     RabbitMq消息接收... 4 1.3     Ex ...

  9. 网络协议学习笔记(八)DNS协议和HttpDNS协议

    概述 上一篇主要讲解了流媒体协议和p2p协议,现在我给大家讲解一下关于DNS和HttpDNS的相关知识. DNS协议:网络世界的地址簿 在网络世界,也是这样的.你肯定记得住网站的名称,但是很难记住网站 ...

随机推荐

  1. 理解Java方法增强

    在实际开发中,我们往往需要对某些方法进行增强,常用的方法增强的方式有三种. 类继承 .方法覆盖 必须控制对象创建,才能使用该方式 装饰者模式方法加强 必须和目标对象实现相同接口或继续相同父类,特殊构造 ...

  2. X264-编码模块和NAL打包输出

    在上一篇介绍了编码器的VCL编码操作,分析了函数x264_slice_write().函数x264_slice_write()里有四个关键模块,分别是宏块分析模块.宏块编码模块.熵编码模块和滤波模块, ...

  3. 百度云部署SSL证书

    查找中间证书 为了确保兼容到所有浏览器,我们必须在阿里云上部署中间证书,如果不部署证书,虽然安装过程可以完全也不会报错,但可能导致Android系统,Chrome 和 Firefox等浏览器无法识别. ...

  4. Win7共享只看到部分文件

    把192.168.70.88这台机器的Android目录做为共享文件夹. 共享端:windows server 用户端:其它pc机安装windows7 或windows 10 在用户端只能看到部分文件 ...

  5. Ubuntu下部署Shipyard管理docker

    使用k8s对于我这种新人来说,难度有点大.遂尝试使用Shipyard这个docker web ui工具来进行管理,以方便入门. 首先,我们还是需要在我们的主机上安装docker. 然后官方提供了自动安 ...

  6. 如何有效的清理yum缓存

    如果遇到下面问题,请执行下面命令   yum clean all   #清除缓存

  7. win10系统易升更新不成功c盘也满了,解决方法

    删除临时更新文件: 1)同时按下Windows键和R键,打开运行,输入services.msc 2)找到WindowsUpdate服务项,右键选择禁用. 3)打开c:\windows\Software ...

  8. (day44)css样式、css布局

    目录 一.css样式 (一)文字样式 (1)文字字体font-family (2)字体大小font-size (3)字体粗细font-weight (4)字体颜色color (二)文本样式 (1)文字 ...

  9. 迪杰斯特拉算法完整代码(Java)

    package com.rao.graph; import java.util.*; /** * @author Srao * @className Dijkstra * @date 2019/12/ ...

  10. web框架--tornado之cookie与session初识

    cookie的本质其实就是在浏览器端保存的键值对, 每当浏览器端发送一次请求, 都会将这些键值对附加在请求中并发送给服务器端. 一.目录结构 二.main_pro.py #!/usr/bin/env ...