写在前面的废话:马上要找工作了,做了一年的.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. 从未被Google过 #NerverBeenGoogled

    我相信大家都用Google搜索互联网上的东西,Google会跟踪你搜索的所有内容,但是你或许不知道,他们也记录着从未被Google过的内容.我有个清单,这些是有史以来从未被Google过的一些东西1. ...

  2. 网络协议SNMP分析技术

    内容一: 1. 打开Ethereal软件开始抓包, 输入命令: snmputil get [目标主机IP地址] public .1.3.6.1.2.1.1.2.0 停止抓包.对SNMP包进行过滤. 2 ...

  3. windows经典主题 桌面颜色(R58 G110 U165)

  4. SQLServer常用快捷键汇总

    菜单激活键盘快捷键 操作 SQL Server 2017 SQL Server 2008 R2 移到 SQL Server Management Studio 菜单栏 Alt Alt 激活工具组件的菜 ...

  5. Windows Server2008 R2 服务器域名设置Https安全证书访问

    域名支持Https访问设置 1.首先登陆域名申办公司的域名管理账号添加TXT域名解析信息 以新网域名公司为例:http://dcp.xinnet.com,输入域名:www.xxx.com和密码登录即可 ...

  6. 爬虫---Beautiful Soup 反反爬虫事例

    前两章简单的讲了Beautiful Soup的用法,在爬虫的过程中相信都遇到过一些反爬虫,如何跳过这些反爬虫呢?今天通过知乎网写一个简单的反爬中 什么是反爬虫 简单的说就是使用任何技术手段,阻止别人批 ...

  7. 9-剑指offer: 二进制中1的个数

    题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 代码 class Solution { public: int NumberOf1(int n) { if(n==0) re ...

  8. JVM 学习资料

    资料 网址 JVM Options - The complete reference http://jvm-options.tech.xebia.fr/ Java HotSpot VM Options ...

  9. day21_7.25 面向对象之继承

    一.继承 什么是继承? 继承是一种关系,就是描述两者之间什么是什么的关系. 在程序中,继承描述的是类与类之间的关系. 例如a如果继承了b,a就具备了b的所有变量与方法,可以直接调用. class B: ...

  10. 微信小程序 - 组件 | 自定义组件 | 组件事件传递页面

    组件 小程序允许我们使用自定义组件的方式来构建页面 类似Vue的小组件 自定义组件 类似于页面,一个自定义组件由 json, wxml, wxss, js 4个文件组成 1.创建 1.创建compon ...