java基础—网络编程
一、网络参考模式
OIS(Open System Interconnection开放系统互连)参考模型。
- 数据包的传输过程
- 数据包的传输过程
TCP/IP参考模型(TCP/IP模型是OIS的简化模型)
七层描述:
物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后再转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。
数据链路层:主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。
网络层:主要将下层接收到的数据进行IP地址(例,192.168.0.1)的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。
传输层:定义了一些传输数据的协议和端口号(WWW端口号80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层叫做段。
会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接收会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)。
表示层:主要是进行对接收的数据进行解释,加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够识别的东西(如图片、声音等)。
应用层:主要是一些终端的应用,比如说FTP(各种文件下载)、WEB(IE浏览)、QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西,就是终端应用)。
二、网络通讯要素
IP地址:InetAddress
网络中设备的标识
不易记忆,可用主机名。
InetAddress ip = InetAddress.getLocalHost(); //获取本地主机IP地址对象
String adress=ip.getHostAddress();//返回 IP 地址字符串
String name=ip.getHostName();//获取此 IP 地址的主机名。
端口号
用于标识进程(应用程序)的逻辑地址,不同进程的标识。
有效端口:0~65535,其中0~1024系统使用或保留端口。
传输协议(通讯的规则)
**常见协议:**UDP、TCP。
UDP的特点:
将数据及源和目的封装成数据包中,不需要建立连接。
每个数据报的大小在限制在64k内。
因无连接,是不可靠协议。
不需要建立连接,速度快。
TCP的特点:
建立连接,形成传输数据的通道。
在连接中进行大数据量传输。
通过三次握手完成连接,是可靠协议。
必须建立连接,效率会稍低。
三、域名解析
- 域名解析,最先走是本地的hosts(C:\WINDOWS\system32\drivers\etc\hosts)文件,解析失败了,才去访问DNS服务器解析、获取IP地址。
四、UDP协议-发送端&接收端
Socket
Socket就是为网络服务提供的一种机制。
通信的两端都有Socket。
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
UDP传输
DatagramSocket(用来发送和接收数据报包的套接字)与DatagramPacket(数据报包)。
建立发送端,接收端。
建立数据包。
调用Socket的发送接收方法。
关闭Socket。
发送端与接收端是两个独立的运行程序。
示例:
- UDP发送端:
import java.net.*;
class UDPSendDemo
{
public static void main(String[] args) throws Exception
{
System.out.println("…………发送端启动");
//如果发送端端口未指定,就会随机分配未被使用的端口。
DatagramSocket ds=new DatagramSocket(8888);
String str="UDP来了,请查收!";
byte[] buf=str.getBytes();
//使用DatagramPacket将数据封装到该对象包中。
DatagramPacket dp=
new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.0.103"),10000);
// 通过udp的socket服务将数据包发送出去,使用send方法。
ds.send(dp);
ds.close();
}
}
- UDP接收端
import java.net.*;
class UDPReceDemo
{
public static void main(String[] args) throws Exception
{
System.out.println("…………接收端启动");
//建立UPDsocket服务。
DatagramSocket ds=new DatagramSocket(10000);
//创建数据包。
byte[] buf =new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
// 使用接收方法将数据存储到数据包中。
ds.receive(dp);
// 通过数据包对象的方法,解析其中的数据,比如:地址,端口,数据内容
String ip=dp.getAddress().getHostAddress();
int port=dp.getPort();
String text=new String (dp.getData(),0,dp.getLength());
System.out.println(ip+"--"+port+"--"+text);
//关闭资源
ds.close();
}
}
- 输出结果:
五、TCP协议(客户端&服务端)
- TCP协议:客户端(Client)首先与服务端(Server)建立连接,形成通道(其实就是IO流),然后,数据就可以在通道之间进行传输,并且单个Server端可以同时与多个Client端建立连接。
TCP客户端:
- 客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过
getInputStream(),getOutputStream()
获取即可。与服务端通讯结束后,关闭Socket。
- 客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过
TCP服务端:
- 服务端需要明确它要处理的数据是从哪个端口进入的。当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。当该客户端访问结束,关闭该客户端。
示例(文本转换):
- 客户端:
import java.io.*;
import java.net.*;
class TransClient
{
public static void main(String[] args) throws Exception
{
//建立Socket客户端
Socket s=new Socket("192.168.0.103",10000);
//获取键盘录入
BufferedReader br=
new BufferedReader(new InputStreamReader(System.in));
//socket输入流,获取服务端返回的大写数据
BufferedReader br1=
new BufferedReader(new InputStreamReader(s.getInputStream()));
//socket输出流
PrintWriter pw=
new PrintWriter(s.getOutputStream(),true);
String line=null;
while ((line=br.readLine())!=null)
{
if ("over".equals(line))
{
break;
}
pw.println(line);
//读取服务端发回来的数据
String str=br1.readLine();
System.out.println(str);
}
s.close();
}
}
- 服务端
import java.io.*;
import java.net.*;
class TransServer
{
public static void main(String[] args) throws Exception
//创建服务端ServerSocket
ServerSocket ss=new ServerSocket(10001);
//获取Socket对象
Socket s=ss.accept();
//获取ip
String ip=s.getInetAddress().getHostAddress();
System.out.println(ip+"……………connect");
//获取Socket输出流并装饰
PrintWriter pw=
new PrintWriter(s.getOutputStream(),true);
//获取Socket读取流并装饰
BufferedReader br=
new BufferedReader(new InputStreamReader(s.getInputStream()));
String line=null;
while ((line=br.readLine())!=null)
{
System.out.println(line);
//将客户端发过来的信息转为大写后发送给客户端
pw.println(line.toUpperCase());
}
s.close();
ss.close();
}
}
- 输出结果: