------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、网络通讯的要素:
IP地址:每台网络设备的唯一标识,常用的IPv4协议,ip地址有四段0~255的数字组成
端口号:设备中网络程序的标识号,tomcat服务器默认端口8080,mysql默认端口3306
传输协议:TCP和UDP
二、网络通讯流程:域名解析
由于ip地址不容易记忆,所以出现了域名概念,一个ip可以对应多个域名,但是一个域名只能对应一个ip,比如百度
的域名:www.baidu.com。域名可以理解为手机通讯录,手机号不容易记忆,所以将手机号标识名字。
在浏览器中访问一个域名时,浏览器首先会访问DNS服务器,DNS服务器会根据域名找到对应的ip并返回给浏览器
然后再根据ip地址进行访问并进行数据传输。所以当我们知道百度的ip地址,可以直接输入ip地址访问,提高速度。
三、网络参考模型:
网络数据的传输其实就是数据打包拆包的过程:从应用层到物理层就是打包,从物理层到应用层就是拆包
TCP/IP模型在OSI模型的基础上进行简化
四、Socket:java.net包中的一个类,这个类为网络服务提供一种机制,网络通讯的两端都有socket,数据就是在两个socket之间通过io进行传输
五、InetAddress:用于描述ip的类,此类中没有构造函数,但是有非静态方法,单例设计模式
InetAddress getByAddress(byte[] addr) :根据原始ip地址,返回InetAddress对象
InetAddress getByAddress(String host, byte[] addr) :根据主机名和 IP 地址创建 InetAddress。
InetAddress getByName(String host) :根据主机名返回InetAddress对象
InetAddress getByAddress(String host, byte[] addr) :根据主机名和 IP 地址创建 InetAddress。
InetAddress getByName(String host) :根据主机名返回InetAddress对象
String getHostAddress() :获取ip地址的字符串形式
String getHostName() :获取主机名。
static InetAddress getLocalHost() :返回本地主机,为静态方法
六、TCP和UDP
UDP:面向无连接,通讯时不需要建立连接
将数据封装在数据报包中,且每个数据报包大小在64k内
因为不需要建立连接,所以是不安全的,但是传输速度快
一般用于聊天软件,视频通话软件等
TCP:面向有连接,在通讯时必须建立连接,形成一个数据通道
通过三次握手完成连接,是安全的
适合大数据传输,比如下载工具等软件
代码示例1:通过UDP的形式发送和接收数据
import java.net.*;
class Send//发送端
{
public static void main(String[] args) throws Exception
{
//1.创建udp服务,通过new DatagramSocket
DatagramSocket ds = new DatagramSocket(45000);
//2.将字节数组封装到数据包中,
//通过DatagramPacket(byte[] buf, int length, InetAddress address, int port)
byte[] buf = "发送数据".getBytes();
DatagramPacket dp =
new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.100"),10000);
//3.将数据包发送出去,通过send方法
ds.send(dp);
//4.关闭资源
ds.close();
}
}
class Receive//接收端
{
public static void main(String[] args) throws Exception
{
//1.创建udp服务,通过new DatagramSocket,设定端口
DatagramSocket ds = new DatagramSocket(10000);
while (true)
{
//2.定义数据包,用于存储数据
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//3.通过receive方法接收数据包并将数据存储进字节数组
ds.receive(dp);
String data = new String(dp.getData(),0,dp.getLength());
String ip = dp.getAddress().getHostAddress();//获取发送端的ip
int port = dp.getPort();//获取发送端的端口号
System.out.println(ip+"::"+port+"::"+data);
}
//关闭资源
ds.close();
}
}
代码示例2:使用TCP的方式发送和接收数据
import java.io.*;
import java.net.*;
class TcpClient
{
public static void main(String[] args) throws Exception
{
//创建socket服务,指定主机和端口
Socket s = new Socket("192.168.1.100",10003);
//获取输出流,用于发送数据
OutputStream out = s.getOutputStream();
out.write("客户端数据".getBytes());
s.close();
}
}
class TcpService
{
public static void main(String[] args) throws Exception
{
//创建服务端socket服务,并监听端口
ServerSocket ss = new ServerSocket(10003);
//通过accept方法获取连接的客户端对象
Socket s = ss.accept();
//获取ip
String ip = s.getInetAddress().getHostAddress();//获取ip
System.out.println(ip+"连接了!");
//通过客户端对象获取客户端的输入流
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
String data = new String(buf,0,len);
int port = s.getPort();//获取端口
System.out.println(ip+"::"+port+"::"+data);
s.close();
}
}
练习1:使用TCP进行文件复制,也就是客户端上传文件到服务器
import java.io.*;
import java.net.*;
class Client
{
public static void main(String[] args)throws Exception
{
//建立socket服务,指定ip和端口号
Socket s = new Socket("192.168.1.110",10005);
//定义字符缓冲流对象,用于读取将要复制的文件
BufferedReader bfr =
new BufferedReader(new FileReader("UploadText.java"));
//定义打印流对象,用于传输数据给服务器
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
String line =null;
while ((line=bfr.readLine())!=null)
{
out.println(line);
}
//传输完毕后,关闭socket中的输出流,告诉服务器,数据已经传输完毕
s.shutdownOutput();
//定义字符输入流对象,用于读取服务器返回的数据
BufferedReader bfr2 =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String str = bfr2.readLine();
System.out.println(str);
bfr.close();
s.close();
}
}
class Server
{
public static void main(String[] args)throws Exception
{
//建立服务器中ServerSocket对象
ServerSocket ss = new ServerSocket(10005);
//通过accept方法获取客户端的socket对象
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();//获取ip地址
System.out.println(ip+"连接了!");
//定义打印流,用于将数据写入新文件
PrintWriter pw = new PrintWriter(new FileWriter("copy.txt"),true);
BufferedReader bfw2 =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while ((line=bfw2.readLine())!=null)
{
pw.println(line);
}
//定义打印流,将提示信息返给客户端
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
out.println("上传成功!");
pw.close();
s.close();
ss.close();
}
}
练习2:多线程下上传图片,实现多用户上传并且可以指定文件
import java.io.*;
import java.net.*;
//客户端类
class Client
{
public static void main(String[] args)throws Exception
{
//args为用户传入的文件绝对路径
if (args.length!=1)
{
System.out.println("请选择一个jpg文件");
return ;
}
//定义文件对象
File f = new File(args[0]);
//判断是否存在和是否是文件
if (!(f.exists() && f.isFile()))
{
System.out.println("文件不存在或者不是jpg文件");
return ;
}
//判断是否为jpg文件
if (!(f.getName().endsWith(".jpg")))
{
System.out.println("请选择一个jpg文件");
return ;
}
//为了防止用于将过大的文件更改后缀名上传,可以进行判断文件大小
if (f.length()>1024*1024*8)
{
System.out.println("文件超过限制大小");
return ;
}
//建立socket服务,指定ip和端口
Socket s = new Socket("192.168.1.110",10006);
//定义字节缓冲流兑现,用于读取文件
BufferedInputStream bfis =
new BufferedInputStream(new FileInputStream(f));
OutputStream out = s.getOutputStream();
int by = 0;
while ((by=bfis.read())!=-1)
{
out.write(by);
out.flush();
}
s.shutdownOutput();//传输完毕后关闭流
//用于读取服务器返回的信息
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
String info = new String(buf,0,len);
System.out.println(info);
bfis.close();//先关闭流
s.close();//再关闭socket
}
}
//服务器端多线程类
class PicThread implements Runnable
{
private Socket s;
PicThread(Socket s)//将客户端的socket作为构造函数的参数,一初始化就要有socket
{
this.s = s;
}
public void run()
{
int count = 1;//定义计数器,用于上传一样文件时,给文件命名
String ip = s.getInetAddress().getHostAddress();
try
{
System.out.println(ip+"连接了!");
BufferedInputStream bfis =
new BufferedInputStream(s.getInputStream());
File file = new File(ip+"("+count+")"+".jpg");
//判断文件是否存在,存在就计数器就加1给文件命名
while (file.exists())
{
file = new File(ip+"("+(count++)+")"+".jpg");
}
FileOutputStream fos = new FileOutputStream(file);
int by = 0;
while ((by=bfis.read())!=-1)
{
fos.write(by);
}
OutputStream out = s.getOutputStream();
out.write("上传成功".getBytes());//返回数据给客户端
fos.close();
s.close();
}
catch (Exception e)
{
throw new RuntimeException("上传图片失败");
}
}
}
class Server
{
public static void main(String[] args)throws Exception
{
ServerSocket ss = new ServerSocket(10006);
//while可以继续上传
while (true)
{
Socket s = ss.accept();
new Thread(new PicThread(s)).start();
}
}
}
六、tomcat服务器:免费开源的javaweb服务器,我们也可以自定义服务器。
七、URL和URLConnection
URL:是一个浏览器地址封装类
常用方法
String getFile() :获取此 URL 的文件名。
String getHost() :获取此 URL 的主机名(如果适用)。
String getPath() :获取此 URL 的路径部分。
int getPort() :获取此 URL 的端口号。
String getProtocol() :获取此 URL 的协议名称。
String getQuery() :获取此 URL 的查询部
URLConnection:将socket进行封装,提供更方便的访问服务器的方法
String getHost() :获取此 URL 的主机名(如果适用)。
String getPath() :获取此 URL 的路径部分。
int getPort() :获取此 URL 的端口号。
String getProtocol() :获取此 URL 的协议名称。
String getQuery() :获取此 URL 的查询部
URLConnection:将socket进行封装,提供更方便的访问服务器的方法
通过getInputStream获取socket中的输入流对象