java学习之旅(day.18)
网络编程
概述
计算机网络:自己百度吧
网络编程的目的:传播交流信息、数据交换、通信
想要达到这个效果需要什么:
- 如何准确的定位网络上的一台主机 端口 定位到这个计算机上的某个资源
- 找到了这个主机,如何传输数据呢?
javaWeb开发 :网页编程 B/S架构
网络编程:主要针对TCP/IP C/S架构
网络通信的要素
如何实现网络的通信?
通信双方地址:
- IP
- 端口号
规则:网络通信的协议
http ftp smtp等
IP地址
IP地址:InetAddress(没有构造器,就不用new了,new不了,用静态方法)
可以唯一的定位一台网络上的计算机
一些特殊的IP,如:127.0.0.1 代表本机(localhost)
IP地址的分类,分类方式有两种
通过IP地址分类 ipv4/ipv6
- ipv4 像127.0.1,是由4个字节组成,每个字节的长度是0-255,ipv4都给外国人了,亚洲就那几个吧,早用光了
- ipv6 128位,8个无符号整数 0-9 a-e
ipv6写法:
2001:0bb2:aaaa:0000:0000:1aaa:1311:0025
通过公网(互联网使用)还是私网(局域网使用)分类
局域网:192开头的,专门给组织内部使用的
ABCD类地址有时间自己查查
域名的诞生就是为了解决记忆IP问题
package com.zhang.WLBC.Lesson01;
import java.net.InetAddress;
import java.net.UnknownHostException;
//测试IP
public class TestInetAddress {
public static void main(String[] args) {
//InetAddress z=new InetAddress();没有构造器,无法new,只能通过它的静态方法把他返回过来
try {
//查询本机地址
InetAddress inetAddress1=InetAddress.getByName("127.0.0.1");//通过获取名字返回 这就代表一个IP对象 //静态方法返回的就是本身这个对象
System.out.println(inetAddress1);
InetAddress inetAddress3=InetAddress.getByName("localhost");
System.out.println(inetAddress3);//localhost/127.0.0.1
InetAddress inetAddress4=InetAddress.getLocalHost();
System.out.println(inetAddress4);//DESKTOP-VKFSHV1/192.168.1.3
//查询网站的IP地址
InetAddress inetAddress2=InetAddress.getByName("www.baidu.com");//跟ping是一样的作用
System.out.println(inetAddress2);//www.baidu.com/39.156.66.18
//常用方法
System.out.println(inetAddress2.getAddress());
System.out.println(inetAddress2.getCanonicalHostName());//获得规范的名字
System.out.println(inetAddress2.getHostAddress());//IP
System.out.println(inetAddress2.getHostName());//域名,或自己电脑的名字
} catch (UnknownHostException e) {
e.printStackTrace();
}
//上面报错了(未知的主机异常),用try catch捕获一下
}
}
端口
端口表示计算机上一个程序的进程,一个端口对应一个程序的进程
不同的进程有不同的端口号,用来区分软件
端口被规定0-65535
分为TCP端口和UDP端口,单个协议下,端口号不能冲突,但是不同协议下的端口号可以相同。如:TCP:80与UDP:80
端口分类-
公有端口:0-1023
- HTTP:80
- HTTP5:443
- FTP:21
- Telent:23
程序注册端口:1024-49151,分配给用户或程序
- Tomcat:8082
- MySQL:3306
- Oracle:1521
动态或私有端口:49152-65535
常见的dos命令
netstat -ano 查看所有的端口
netstat -ano|findstr "5900" 查看指定的端口
tasklist|findstr "8696" 查看指定端口的进程
package com.zhang.WLBC.Lesson01;
import java.net.InetSocketAddress;
public class TestInetSocketAddress {
public static void main(String[] args) {
InetSocketAddress socketAddress=new InetSocketAddress("127.0.0.1",80);//这个类可以new
System.out.println(socketAddress);///127.0.0.1:80
InetSocketAddress socketAddress1=new InetSocketAddress("localhost",80);//这个类可以new
System.out.println(socketAddress1);//localhost/127.0.0.1:80
//里面的方法
System.out.println(socketAddress.getAddress());// /127.0.0.1
System.out.println(socketAddress.getHostName());//127.0.0.1
System.out.println(socketAddress.getPort());// 80
}
}
通信协议
协议:约定,就像现在说的是汉语才能听懂,说外语就jj了
网络通信协议:针对网络产生的协议
TCP/IP协议簇:实际上是一组协议
TCP:用户传输协议 类似于打电话
UDP:用户数据报协议 类似于发短信
比较出名的协议
- TCP:用户传输协议
- IP:网络互联协议
TCP与UDP对比
TCP:类似打电话
- 连接,稳定
- 三次握手,四次挥手
建立稳定连接至少要三次
断开连接至少要四次
- 客户端,服务端连接
- 传输完成就会释放连接,效率低
UDP:类似发短信
- 不连接,不稳定
- 客户端,服务端没有明确的界限
- 不管有没有准备好,都可以发给你
- DDOS:洪水(饱和)攻击,也就是人海战术吧
TCP实现聊天
聊天就要两个人(客户端和服务器)
得编写两个类:客户端、服务器
客户端
- 通过socket连接服务器
- 发送消息
package com.zhang.WLBC.Lesson02;
//运行时先启动服务端,再启动客户端
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
//客户端
public class TcpClientDemo01 {
public static void main(String[] args) {
Socket socket=null;
OutputStream os=null;
//1.客户端连接服务器要先知道服务器的地址,所以对服务器来说得先有一个地址,做一个地址
//连接
try {
InetAddress severIP=InetAddress.getByName("127.0.0.1");//要连接的地址
//2.端口号
int port =9999;
//把上面两行和服务端连接
//用socket 创建一个socket连接
socket=new Socket(severIP,port);//这样就连接到服务端了,这里会出现异常,要把catch中的作用域提升到最大(把UnknownHostException改为Exception)把UnknownHostException改为Exception
//3.发送消息,用到IO
os=socket.getOutputStream();
os.write("你好,我正在自学java".getBytes());//然后就是客户端接收了
} catch (Exception e) {//catch (UnknownHostException e) {
e.printStackTrace();
}finally {
if (os!=null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null) {
try {
socket.close();//继续提升作用域,捕获异常
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服务器
建立服务的端口Seversocket
通过accept等待客户端的连接,会返回客户端连接过来的socket
接收用户的消息
package com.zhang.WLBC.Lesson02;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务端
public class TcpSeverDemo01 {
public static void main(String[] args) {
//提升作用域?
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
//1.做一个地址localhost:9999,再去客户端让客户端连这个9999
serverSocket = new ServerSocket(9999);
//2.等待客户端连接过来
socket = serverSocket.accept();//这里的Socket就是客户端连接过来的socket
//3.读取客户端的消息
is = socket.getInputStream();
/* byte[] buffer=new byte[1024];//用缓冲区去接
int len;
while ((len=is.read(buffer))!=-1){//读
String msg=new String(buffer,0,len);//然后写出去,new一个string后拼接上去
System.out.println(msg);
//但一般不这样写了,因为有中文的话会乱码
}
*/
//而用管道流
baos = new ByteArrayOutputStream(); //把输入流通过管道流接一下,再输出来
byte[] buffer = new byte[1024];//用缓冲区去接
int len;
while ((len = is.read(buffer)) != -1) {//读
baos.write(buffer, 0, len);
}
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源,先开后关
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!= null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket != null) {
try {
serverSocket.close();//这几行直接加不进来,要提升作用域
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
//也可以不写try catch,直接抛出异常
文件上传
读取后,把文件变成一个流,再传出去
客户端(路径一直不对,报错)
package com.zhang.WLBC.Lesson02;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
//客户端读取发送文件
public class TcpClientDemo02 {
public static void main(String[] args) throws Exception{
//1.创建一个socket连接
Socket socket=new Socket(InetAddress.getByName("127.0.0.1"),9000);
//2.创建一个输出流
OutputStream os=socket.getOutputStream();
//3.读取文件
FileInputStream fis= new FileInputStream(new File("B.PNG"));
//4.写出文件
byte[] buffer=new byte[1024];//缓冲区
int len;
while ((len=fis.read(buffer))!=-1){
os.write(buffer,0,len);
}
//通知服务器,我已经结束了
socket.shutdownOutput();//我已经传输完了
//确定服务器接收完毕才能断开连接,再在服务器端通知客户端我接收完毕了
InputStream inputStream=socket.getInputStream();
ByteArrayOutputStream baos=new ByteArrayOutputStream();//传过来的东西不认识,只有通过管道流才能认识
byte[] buffer2=new byte[1024];
int len2;
while ((len2=inputStream.read())!=-1){
baos.write(buffer2,0,len2);
}
System.out.println(baos.toString());
//5.关闭资源
baos.close();
inputStream.close();
fis.close();
os.close();
socket.close();
}
}
服务器端
package com.zhang.WLBC.Lesson02;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务端接收文件
public class TcpSeverDemo02 {
public static void main(String[] args) throws Exception{
//1.创建服务端口
ServerSocket serverSocket=new ServerSocket(9000);
//2.监听客户端的连接
Socket socket=serverSocket.accept();//阻塞式监听,会一直等待客户端连接
//3.获取输入流
InputStream is=socket.getInputStream();//这样就把文件拿到了
//4.文件输出
FileOutputStream fos=new FileOutputStream(new File("receive.PNG"));
byte[] buffer=new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
//通知客户端我接收完毕了
OutputStream os=socket.getOutputStream();
os.write("我接收完毕了,可以断开了".getBytes());
//关闭资源
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
Tomcat
服务端
- 自定义s
- 也可以用Tomcat服务器
客户端
- 自定义c
- 浏览器B
UDP消息发送
相当于发短信:不用连接,只需知道对方的地址就可
发送消息
package com.zhang.WLBC.Lesson02.Lesson03;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//不需要连接到服务器
public class UdpClientDemo01 {
public static void main(String[] args) throws Exception{
//1.建立一个socket
DatagramSocket socket=new DatagramSocket();//用来发东西的 此处要抛出异常
//2.建个包
String msg="hello";
new DatagramPacket(msg.getBytes(),0,msg.getBytes().length);//msg.getByte 变成数组
//发送给谁
InetAddress localhost=InetAddress.getByName("localhost");
int port=9090;
DatagramPacket packet=new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port);//msg.getByte 变成数组
//数据 数据长度的起始 要发给谁
//3.发送包(通过socket发送包)
socket.send(packet);
//4.关闭资源
socket.close();// 包不用关
}
}
接收消息
package com.zhang.WLBC.Lesson02.Lesson03;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
//服务器端要开放端口,其实还是好比要等待客户端的连接
public class UdpServerDemo01 {
public static void main(String[] args) throws Exception{
//开放端口
DatagramSocket socket=new DatagramSocket(9090);
//接收数据包
byte[] buffer=new byte[1024];
DatagramPacket packet=new DatagramPacket(buffer,0,buffer.length);
socket.receive(packet);//阻塞接收(随时等待接收)
System.out.println(packet.getAddress());//输出包裹从哪来的
System.out.println(packet.getData());// [B@45ee12a7 data是一个byte,要转为String(new一个string),见下一行
System.out.println(new String(packet.getData(),0,packet.getLength()));//得到包裹的内容
//关闭连接
socket.close();
}
}
实现聊天
循环发送消息
package com.zhang.WLBC.Lesson02.Lesson03.chat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
//两者互为发送者和接收者
public class UdpSenderDemo01 {
public static void main(String[] args) throws Exception{
DatagramSocket socket=new DatagramSocket(8888);
//准备数据,聊天,需要从控制台读取(System.in)
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in ));
while (true) {
String data = reader.readLine();//读取一行
byte[] dates = data.getBytes();//转换成数据,因为data是不可读的,要转换为字节
DatagramPacket packet = new DatagramPacket(dates, 0, dates.length, new InetSocketAddress("localhost", 6666));//这里需要数据,所以要准备数据
socket.send(packet);
if (data.equals("bye")) {
break;
}
}
socket.close();
}
}
循环接收消息
package com.zhang.WLBC.Lesson02.Lesson03.chat;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UdpReceiveDemo01 {
public static void main(String[] args) throws Exception{
DatagramSocket socket=new DatagramSocket(6666);
//实现循环接收
while (true){
//准备接收包裹
byte[] container=new byte[1024];
DatagramPacket packet=new DatagramPacket(container,0,container.length);
socket.receive(packet);////这个packet需要一个地方去放置它,所以需要一个准备接收的包裹
//接收过来的消息还得读一下
//断开连接(接收的数据为bye的时候)
byte[] data=packet.getData();
String receiveData=new String(data,0,data.length);//读取接收到的消息
System.out.println(receiveData);
if (receiveData.equals("bye")){
break;
}
}
socket.close();
}
}
UDP多线程在线咨询
两个人都可以是发送方,也都可以是接收方
java学习之旅(day.18)的更多相关文章
- Java学习之旅开篇:运行机制及环境搭建
在写这篇博客之前,我想对自己进行简单概括:我从事软件开发工作已经三年多了,并且一直在从事.NET相关项目的开发.为什么突然间想学习Java呢?有以下几个原因: 1. 开发程序三年多来,已经对.NET相 ...
- Java学习之旅基础知识篇:面向对象之封装、继承及多态
Java是一种面向对象设计的高级语言,支持继承.封装和多态三大基本特征,首先我们从面向对象两大概念:类和对象(也称为实例)谈起.来看看最基本的类定义语法: /*命名规则: *类名(首字母大写,多个单词 ...
- 第一篇,java学习之旅
在java的这座殿堂中,我才刚刚推开了大门,就像是在岔路口找到了一条,走向前进java大门的路. 下面是一些java算法的问题 第一题: package project.model; import j ...
- Java学习之旅(一):探索extends
鄙人为兴趣爱好,0基础入门学习Java,有些心得想法,记录于此,与君分享. 然毕竟新手,学识尚浅,错误之处,希望多多指正批评,也是对我最大的帮助! 前言:本篇文章,主要讨论在子类继承父类之后,一些继承 ...
- Java学习之旅基础知识篇:数组及引用类型内存分配
在上一篇中,我们已经了解了数组,它是一种引用类型,本篇将详细介绍数组的内存分配等知识点.数组用来存储同一种数据类型的数据,一旦初始化完成,即所占的空间就已固定下来,即使某个元素被清空,但其所在空间仍然 ...
- Java学习之旅基础知识篇:数据类型及流程控制
经过开篇对Java运行机制及相关环境搭建,本篇主要讨论Java程序开发的基础知识点,我简单的梳理一下.在讲解数据类型之前,我顺便提及一下Java注释:单行注释.多行注释以及文档注释,这里重点强调文档注 ...
- 我的java学习之旅--一些基础
(因为我粗略学过C,C++,Python,了解过他们的一些语法,所以为了使得java的入门更为顺畅,便会忽略一些和C语法相类似的地方,着重点明一些java自己的特色之处.也减轻一下自己写文字的负担.) ...
- Java学习之旅(二):生病的狗1(逻辑推导)
前言:本篇文章属于个人笔记,例化了一些代码,不知是否合理,请指教. 中午看到一位同学的面试题,觉得很烧脑,烧脑不能一个人烧,要大家一起烧. 村子中有50个人,每人有一条狗.在这50条狗中有病狗(这种病 ...
- java学习之旅
jar文件其实就是一个压缩包,里面包含很多class文件(一个class文件是一个类的字节码).方便在网络上传输.可以规定版本号,更容易进行版本控制. var只能在方法内使用,不能用于定义成员变量. ...
- 面向对象编程(OOP)的五大特征-java学习之旅(1)
这是Alan Kay关于第一个成功的面向对象语言SmallTalk的总结: 1.所有的东西都是对象.可将对象想象成一种新型的变量:它保存着数据,但是可要求它对自身进行操作,理论上讲,可从要解决的问题身 ...
随机推荐
- 深度剖析 Spring 框架在 Java 应用开发中的优势与应用
Spring 是用于企业 Java 应用程序开发的最流行的应用程序开发框架.全球数百万开发人员使用 Spring Framework 创建高性能.易于测试和可重用的代码.Spring Framewor ...
- sql 语句系列(分割ip)[八百章之第十四章]
前言 单独列出的章节.因为用处比较多. mysql select SUBSTRING_INDEX(SUBSTRING_INDEX("192.168.1.1",".&quo ...
- c# 解决死锁问题Monitor
前言 在高并发中,一个很关键的问题就是要避免死锁. 那么为什么会产生死锁呢?这种情况多见吗? 举一个例子: 比如方法一中先lock(object1),在lock(object1)中lock(objec ...
- Effective Python:第1条 查询自己使用的Python版本
命令行: python --version:通常可查看python2的版本: python3 --version:通常可查看python3的版本: 代码: import sys print(sys.v ...
- 【Azure APIM】列举几种在APIM 策略中的主动生产的错误语句
问题描述 在为APIM服务配置了诊断日志(Diagnostic Setting),把日志收集在Log A Workspace中,需要验证日志中是否能查看到请求的错误信息. 所以想人为的来制造一些错误. ...
- marquee实现滚动
marquee的基本语法:<marquee> ... </marquee> 参数:1.滚动方向 (direction):left(左).right(右).up(上).down( ...
- D365虚拟机安装
原本有本地VM是2023.3.31安装的,奈何微软不断升级,导致程序一些新特性用不到,例如: 1,Master Planning ---> Planning Optimization, 2,mi ...
- 中国大陆地区维护的Linux操作系统
Linux开源生态丰富,中国大陆地区基于CentOS停服,依托阿里云.腾讯云.华为云三大私营企业,相继发布了自己的开源Linux定制版,很高兴的是他们只是改个名字并没有选择闭门造车,只是官网还是很不耻 ...
- 力扣202(java&python)-快乐数(简单)
题目: 编写一个算法来判断一个数 n 是不是快乐数. 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和.然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终 ...
- 技术门槛高?来看 Intel 机密计算技术在龙蜥社区的实践 | 龙蜥技术
简介: 数据可用不可见是怎么做到的? 编者按:龙蜥社区云原生机密计算 SIG 定位于云原生机密计算底层基础设施,专注于机密计算底层技术.在阿里巴巴开源开放周中, 龙蜥社区机密计算 SIG Mainta ...