------- android培训、java培训、期待与您交流! ----------
1 网络模型:
1.1)OSI参考模型
应用层,表示层,会话层,传输层,网络层,数据链路层,物理层
1.2)TCP/IP参考模型
应用层 传输层 网际层 主机至网络层
网络通讯要素
1.2.1)ip地址
1.2.2)端口号 :数据要发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识
端口一般是:0到6535,windows应用程序一般都占用了0到1024的端口
1.2.3)传输协议TCP和UDP协议
默认回环ip地址127.0.0.1 主机名:localhost
数据封包和数据拆包
/**
例子1:获取本机ip地址
*/
import java.net.*;
class IpDemo
{
public static void main(String[] args)throws Exception
{
/*
获取本机的ip地址和主机名,并返回ip对象
InetAddress i=InetAddress.getLocalHost();
System.out.println(i.toString());
System.out.println("address"+i.getHostAddress());//本机的ip地址
System.out.println("name"+i.getHostName());//主机名
*/
//输入主机名和ip地址都行,返回一个ip对象
InetAddress ia=InetAddress.getByName("www.baibu.com");
System.out.println(ia.toString());
System.out.println("address"+ia.getHostAddress());//本机的ip地址
System.out.println("name"+ia.getHostName());//主机名
}
}
2 UDP
QQ聊天是UDP
2.1)udp特点
2.1.1)将数据及源和目的封装成数据包中,不需要建立链接
2.1.2)每个数据包的大小在限制64kb内
2.1.3)因无连接,是不可靠协议
2.1.4)不需要建立连接,速度快
3 TCP
电话是TCP
3.1)tcp特点
3.1.1)建立连接,形成传输数据的通道
3.1.2)在连接中进行大数据量传输
3.1.3)通过三次握手完成连接,是可靠协议
3.1.4)必须建立连接,效率会稍低
4 Socket
Socket就是为网络服务提供的一种机制
通讯的两端都有Socket
网络通讯其实就是Socket间的通信
数据在两个Socket间通过IO传输
注意:ip最后的数是0的表示是一个网址不能使用,是254的表示广播地址,如果定义这个地址发出去,只要端口对得上,都能接受到信息
/*
需求:通过udp传输方式,将一段文字数据发送出去
思路:
1建立updsocket服务
2提供数据,并将数据封装到数据包中
3通过socket服务的发送功能,将数据包发出去
4关闭资源
*/
import java.net.*;
class UdpSend
{
/*
键盘录入
public static void main(String[] args)throws Exception
{
//建立updsocket服务
DatagramSocket ds=new DatagramSocket(1903);
BufferedReader bur=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=bur.readLine())!=null)
{
if(line.equals("886"))
break;
byte[] buf=line.getBytes();
DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("169.254.0.254"),10000);
//提供数据,并将数据封装到数据包中DatagramPacket(byte[] buf,int length,InetAddress address,int port)
//byte[] buf="udp ge men lai la".getBytes();
//DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("169.254.0.84"),10000);
//通过socket服务的发送功能,将数据包发出去
ds.send(dp);
}
ds.close();
}
*/
public static void main(String[] args)throws Exception
{
//建立updsocket服务
DatagramSocket ds=new DatagramSocket(1903);
//提供数据,并将数据封装到数据包中DatagramPacket(byte[] buf,int length,InetAddress address,int port)
byte[] buf="udp ge men lai la".getBytes();
DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("169.254.0.84"),10000);
//通过socket服务的发送功能,将数据包发出去
ds.send(dp);
ds.close();
}
}
/*
需求:定义一个应用程序,用于接受udp协议传输的数据并处理
思路:
1 定义udpsocket服务
2 定义一个数据包,因为要存储接收到的字节数据,因为数据包对象中有更多功能可以提取字节数据中的不同数据信息
3 通过socket服务的receive方法将收到的数据存入已定义好的数据包中
4 通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上
5 关闭资源
*/
class UdpRece
{
public static void main(String[] args)throws Exception
{
//创建udp socket,建立端点
DatagramSocket ds=new DatagramSocket(10000);
while(true)
{
//定义数据包,用于存储数据
byte[] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
//通过服务的receive方法将收到的数据存入数据包中
ds.receive(dp);
//通过数据包的方法获取其中的数据
String ip=dp.getAddress().getHostAddress();
//获取数据包中的数据:dp.getData() 数据的长度
String data =new String(dp.getData(),0,dp.getLength());
int port=dp.getPort();
System.out.println(ip+"::"+data+"::"+port);
//关闭资源
//ds.close();
}
}
}
/*
这是一个聊天程序
*/
import java.io.*;
import java.net.*;
class UdpSend2 implements Runnable
{
private DatagramSocket dgs;
UdpSend2(DatagramSocket dgs)
{
this.dgs=dgs;
}
public void run()
{
try
{
//键盘录入
BufferedReader bur=new BufferedReader(new InputStreamReader(System.in));
String line=null;
//读取键盘的数据
while((line=bur.readLine())!=null)
{
if("886".equals(line)) //判断结束标记
break;
byte[] buf=line.getBytes();//把字符串转为字节数组
//定义一个数据包,并把数据存储在包中
DatagramPacket dgp=new DatagramPacket(buf,buf.length,InetAddress.getByName("169.254.0.254"),1003);
dgs.send(dgp);//把数据包发送到指定的端口
}
dgs.close();//关闭资源
}
catch(Exception e)
{
throw new RuntimeException("发送失败");
}
}
}
class UdpRece2 implements Runnable
{
private DatagramSocket dgs;
UdpRece2(DatagramSocket dgs)
{
this.dgs=dgs;
}
public void run()
{
while(true)
{
try
{
byte[] buf=new byte[1024];//定义数组
//定义一个数据包
DatagramPacket dgp=new DatagramPacket(buf,buf.length);
dgs.receive(dgp);//接受端口发来的数据,存储在dgp包中,阻塞式语句
String ip=dgp.getAddress().getHostAddress();//得到数据的ip地址
//得到数据包中的内容
String data=new String(dgp.getData(),dgp.getLength());
//得到数据包的端口
int port=dgp.getPort();
System.out.println("ip:"+ip+"..."+"data:"+data+"port:"+port);
}
catch(Exception e)
{
throw new RuntimeException("接受信息失败");
}
}
}
}
class UdpDemo
{
public static void main(String[] args)throws Exception
{
DatagramSocket send=new DatagramSocket();
DatagramSocket rece=new DatagramSocket(1003);//指定端口
UdpSend2 usend=new UdpSend2(send);
UdpRece2 urece=new UdpRece2(rece);
//开启线程
new Thread(usend).start();
new Thread(urece).start();
}
}
4.1 TCP
4.1.1) tcp分客户端和服务端
4.1.2) 客户端对应的对象是Socket
4.1.3)服务器对应的对象是ServerSocket
客户端:
通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机
因为tcp是面向连接的,所以在建立socket服务时
就要有服务端存在,并连接成功,形成通路后,在该通道进行数据的传输
步骤:
1 创建Socket服务,并指定要连接的主机和端口
2 获取对应的输出流对象
3 向流中写入东西
/*
例子:演示tcp传输
*/
import java.io.*;
import java.net.*;
class TcpClient
{
public static void main(String[] args)throws Exception
{
//创建客户端的socket服务,指定目的主机和端口
Socket s=new Socket("169.254.0.84",1003);
//为了发送数据,应该获取socket流中的输出流
OutputStream out=s.getOutputStream();
out.write("tcp ge men lai la".getBytes());
s.close();
}
}
/*
需求:定义TCP传输,定义端点接收数据并打印在控制台上
服务台:
1 建立服务端的socket服务. SeverSocket();并监听一个端口
2 获取连接过来的客户端对象
通过ServerSocket的accept方法,没有连接就会等,所以这个方法是阻塞式的
3 客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据,并打印在控制台
4 关闭服务端(可选)
*/
class TcpServer
{
public static void main(String[] args)throws Exception
{
//建立服务端socket服务,并监听一个端口
ServerSocket ss=new ServerSocket(1003);
//通过accept方法获取连接过来的客户端对象
Socket s=ss.accept();
//获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据
InputStream in=s.getInputStream();
byte[] buf=new byte[1024];
int len=in.read(buf);
System.out.println(new String(buf,0,len));
s.close();//关闭客户端
ss.close();
}
}
/*
例子:键盘录入数据,把数据传到网络流中,客户端读取键盘录入的数据,写到网络流中,服务端把客户端的数据返回大写,客户端读取到服务端返回的数据
*/
import java.io.*;
import java.net.*;
class Socket3
{
public static void main(String[] args)throws Exception
{
Socket s=new Socket("169.254.0.84",1005);
BufferedReader bfr=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bfwout=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
BufferedReader bfrin=new BufferedReader(new InputStreamReader(s.getInputStream()));
String line=null;
while((line=bfr.readLine())!=null)
{
if("over".equals(line))
break;
bfwout.write(line);
bfwout.newLine();
bfwout.flush();
String str=null;
str=bfrin.readLine();
System.out.println(str);
}
s.close();
bfr.close();
}
}
class ServerSocket3
{
public static void main(String[] args)throws Exception
{
ServerSocket ss=new ServerSocket(1005);
Socket s=ss.accept();
String ip=s.getInetAddress().getHostAddress();
System.out.println(ip+"connect...");
BufferedReader bufin=new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bufout=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line=null;
while((line=bufin.readLine())!=null)
{
System.out.println(line);
bufout.write(line.toUpperCase());
bufout.newLine();
bufout.flush();
}
s.close();
ss.close();
}
}
注意:s.shutdownOutput();给输出流加上加上结束标记
/*
上传图片到服务器
*/
import java.io.*;
import java.net.*;
class PicClient
{
public static void main(String[] args)throws Exception
{
if(args.length!=1)
{
System.out.println("请选择一个jpg格式的图片");
return;
}
File file=new File(args[0]);
if(!(file.exists()&&file.isFile()))
{
System.out.println("该文件有问题,要么不存在,要么不是文件");
}
if(!file.getName().endsWith(".jpg"))
{
System.out.println("图片格式错误,请重新选择");
}
if(file.length()>1024*1024*5)
{
System.out.println("图片过大,没安好心");
}
Socket s=new Socket("169.254.0.84",1006);
FileInputStream fis=new FileInputStream(file);
InputStream fisin=s.getInputStream();
OutputStream fosout=s.getOutputStream();
byte[] buf=new byte[1024];
int len=0;
while((len=fis.read(buf))!=-1)
{
fosout.write(buf,0,len);
}
s.shutdownOutput();
byte[] buf2=new byte[1024];
int len2=0;
len2=fisin.read(buf2);
System.out.println(new String(buf2,0,len2));
fis.close();
s.close();
}
}
class PicThread implements Runnable
{
private Socket s;
PicThread(Socket s)
{
this.s=s;
}
public void run()
{
int count=1;
String ip=s.getInetAddress().getHostAddress();
try
{
System.out.println("connect..."+ip);
File file=new File(ip+"("+(count)+")"+".jpg");
while(file.exists())
file=new File(ip+"("+(count++)+")"+".jpg");
FileOutputStream fos=new FileOutputStream(file);
InputStream fisin=s.getInputStream();
byte[] buf=new byte[1024];
int len=0;
while((len=fisin.read(buf))!=-1)
{
fos.write(buf,0,len);
}
OutputStream fosout=s.getOutputStream();
fosout.write("上传图片成功".getBytes());
fos.close();
s.close();
}
catch(Exception e)
{
throw new RuntimeException("文件上传失败");
}
}
}
class PicServer
{
public static void main(String[] args)throws Exception
{
ServerSocket ss=new ServerSocket(1006);
while(true)
{
Socket s=ss.accept();
new Thread(new PicThread(s)).start();
}
//ss.close();
}
}
5 浏览器上的地址一般都是主机名但是socket是地址名,所以他要进行域名解析,找公网的dns服务器,里面都有主机和ip地址的映射表关系,解析完返回来,拿到ip地址再去访问网站
先走本地的host文件,再走公网的DNS服务器
这时候我们就有搞头了!
127.0.0.1是回环地址,是访问本机的,一个地址可以对应多个主机名
1一些恶意网站可以设置:主机名的地址映射关系是127.0.0.1这样它就访问不了恶意网站了
2一些使用软件,要输入注册码,输入注册码的时候它会连接到网站进行更新,可以作上述设置,让他更新失败
3把常用的网址在本地进行映射,以加快速度