一、网络模型
注意:OSI模型的传输层封装了TCP/UDP协议,网络层封装了IP协议,应用层封装了FTP、HTTP等。
二、网络通信的三个要素
1.IP地址:
网络中的设备标识
常用网段:192.168..
本地回环地址:127.0.0.1 localhost
2.端口号:
常用逻辑端口 0-65535(0-1024被系统使用或者保留)
web:80
Mysql:3306
HTTP:8080
3.传输协议
UDP(邮递包裹):聊天、网络视频会议、桌面共享
TCP:下载、打电话
注意:
TCP的3次握手过程:A与B通信,A首先发送消息给B,如果B在,反馈信息给A,然后A在发送信息给B,确定收到B发过来的信息。
InetAddress类:
1.没有构造函数,可通过getLocalHost()方法获取InetAddress对象,此方法是静态的,返回本类对象。
InetAddress i = InetAddress.getLocalHost();
2.常用方法:
1)static InetAddress getByName(String host):获取指定主机的IP和主机名。(最好用ip地址去获取,主机名需要解析)
2)static InetAddress[] getAllByName(String host):在给定主机名的情况下,根据系统上配置的名称服务返回IP地址所组成的数组。返回对象不唯一时,用此方法。
3)String getHostAddress():返回IP地址字符串文本形式,以IP地址为主。
3.如何获取任意一台主机的IP地址对象:
1)功能:返回InetAddress对象
2)对于任意主机,需要指定传入主机名的参数
注意:如果IP地址和对应的主机名,这种映射关系没有在网络上,就不会解析成功,返回的还是指定的IP。
Socket通信
一.Socket:
二、通过IO进行通信
UDP:发送端和接收端
TCP:服务器端和客户端
UDP通信:
发送端:
a、建立UDPSocket服务对象
b、提供数据,并将数据封装到数据包中
c、通过socket服务的发送功能,将数据包发送出去
d、关闭资源
接收端
a、定义UDPSocket服务对象,并监听端口,给接收端序定义数字标识,明确哪些数据过来该应用程序可以处理。
b、定义一个数据包,用来存储接收到的字节数据,因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。
c、通过socket服务的receive方法接收到的数据存入已定义好的数据包中
d、通过数据包对象的特有功能,将这些不同的数据取出进行处理
e、关闭资源
TCP通信:
1.创建Socket对象,指定服务器地址和端口
2.获取Socket流中的输出流getOutputStream(),发送数据
3.关闭资源
服务端:
1.建立服务端的Socket服务ServerSocket,并监听端口
2.获取连接过来的客户端对象accept(),是阻塞式方法
3.客户端如果发送数据,服务端要使用客户端对象,通过getInputStream()处理发送过来的数据
4.关闭客户端(服务端可不关)
注意:
TCP通信容易出现的问题:客户端和服务器都在莫名的等待
因为:客户端和服务器都有阻塞式方法readLine()、accept(),这些方法没有读到结束标记,那么就一直等待,而导致两端都处于等待当中。
处理:可以通过不断打印的方式,判断注意数据是否发送过去,是否有结束标记flush(),newLine(),shutdownOutput(),可以在客户端发送数据结束后,向服务端发送结束标记,也可自定义结束标记(时间戳)。
例子:客户端并发上传图片
客户端:
package demo;
/*
* 定义客户端,向服务器上传图片
*/
import java.net.*;
import java.io.*;
public class UploadPicByThread {
public static void main(String[] args) throws Exception {
//先对上传的文件进行一系列的判断
if(args.length==0){
System.out.println("请选择一个图片");
return ;
}
String fileStr = args[0];
File file = new File(fileStr);
if(!file.exists()){
System.out.println("文件不存在");
return ;//结束主函数
}
if(!args[0].endsWith(".jpg")){
System.out.println("只支持jpg格式的图片");
return ;
}
if(file.length()>1024*1024*5){
System.out.println("图片过大!");
return ;
}
//符合要求后上传图片到服务端
upload(file);
}
//上传图片
public static void upload(File file) throws IOException{
//客户端的Socket服务
Socket socket = new Socket("192.168.1.104",10005);
FileInputStream in = new FileInputStream(file);
OutputStream bufOut = socket.getOutputStream();
InputStream bufIn = socket.getInputStream();
//向服务端上传图片
byte[] buf = new byte[1024];
int len = 0;
while((len=in.read(buf))!=-1){
bufOut.write(buf,0,len);
}
//定义结束标记
socket.shutdownOutput();
//接收服务端反馈
byte[] tbuf = new byte[1024];
int length = bufIn.read(tbuf);
System.out.println(new String(tbuf,0,length));
socket.close();
in.close();
}
}
服务端:
package demo;
/*
* 需求:将客户端发送到服务端的图片保存到硬盘中
*/
import java.net.*;
import java.io.*;
public class DownloadPicByThread {
public static void main(String[] args) throws IOException {
//建立服务端
ServerSocket serverSocket = new ServerSocket(10005);
while(true){
//每获取到新的客户端对象,就开启新的线程
Socket socket = serverSocket.accept();
new Thread(new Download(socket)).start();
}
}
}
//并发上传图片
class Download implements Runnable{
private Socket socket;
private int count = 1;
Download(Socket socket){
this.socket = socket;
}
public void run(){
String ip = socket.getInetAddress().getHostAddress();
System.out.println(ip+"...connect");
FileOutputStream out = null;
InputStream bufIn = null;
OutputStream bufOut = null;
try {
//判断硬盘中文件是否存在,存在就重命名
File path = new File("F:\\pic\\"+count+".jpg");
while(path.exists()){
path = new File("F:\\pic\\"+(count++)+".jpg");
}
out = new FileOutputStream(path);
bufIn = socket.getInputStream();
bufOut = socket.getOutputStream();
//将网络输入流中的数据写到硬盘文件中
int len = 0;
byte[] buf = new byte[1024];
while((len=bufIn.read(buf))!=-1){
out.write(buf,0,len);
}
//向客服端反馈信息
bufOut.write("上传成功!".getBytes());
}catch (IOException e) {
throw new RuntimeException("上传失败");
}finally{
try{
if(out!=null)
out.close();
}catch(IOException e){
throw new RuntimeException("关闭文件写入字节流失败");
}
try{
socket.close();
}catch(IOException e){
throw new RuntimeException("关闭网络流字节流失败");
}
}
}
}
URL
一、概述
URL :统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。
URI:也代表统一资源定位符,它比URL更强大,包括条形码。
二、方法
常用方法:
URL(String spec) 根据 String 表示形式创建 URL 对象
String getProtocol() 获取此 URL 的协议名称
String getHost() 获取此 URL 的主机名(如果适用)
int getPort() 获取此 URL 的端口号
String getPath() 获取此 URL 的资源路径部分
String getFile() 获取此 URL 的文件名(path+query)
String getQuery() 获取此 URL 的查询部分
重点方法:
URLConnection openConnection()
返回一个 URLConnection 对象(子类HttpURLConnection对象),它表示到 URL 所引用的远程对象的连接
InputStream openStream()
打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream (先连接再获取输入流)
URLConnection类中:
InputStream getInputStream() 返回从此打开的连接读取的输入流(Socket流中的方法)
OutputStream getOutputStream() 返回写入到此连接的输出流(Socket流中的方法)
注意:
1)在进行地址访问没有指定端口时,getPort()方法返回-1,则将端口号设置为80,因此上网时默认访问的端口都是80。
2)传输层协议(TCP)访问服务器时,会返回响应头信息与正文主体,而浏览器在访问服务器时只返回正文主体,因其把符合应用层协议(HTTP)的消息部分(响应头)给解析(拆包)了,把正文部分显示在了主体区域内。