主要是两个模型
OSI模型参考模型:
物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
TCP/IP参考模型
主机至网络层、网际层、传输层、应用层
网络通讯的要素
IP地址:互联网协议地址,是IP Address的缩写。是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。本地回环地址为:127.0.0.1,主机名为:LocalHost。可用此IP屏蔽垃圾网站。
Java.net包中有InetAddress类,可通过getByAddress和getByName方法来获取。地址分为IPv4和IPv6,现在主要使用的是IPv4,IPv6还在发展中。
端口号:连接软件时所需要的接口号,有效端口为0~65535,其中0~1012为系统使用或者保留端口。
传输协议:常见协议为TCP和UDP
UDP(用户数据报协议)
将数据及源和目的封装成数据包中,不需要建立连接。每个数据包的大小限制在64k内。
因无连接,所以是不可靠协议,不需要建立连接,速度快。
TCP(传输控制协议)
建立连接,形成传输数据的通道。在连接中进行大数据量传输,通过三次握手完成连接,是可靠协议
必须建立连接,效率会稍低。
Socket(网络服务端点)
Socket就是为网络服务提供的一种机制,通信两端都必须有Socket。网络通信其实就是Socket之间的通信。数据在两个Socket间通过IO传输。
UDP传输
发送端和接收端使用的都是DatagramSocket类,用来发送和接收数据包的套接字。
常用方法:void send(DatagramPacket p)发送数据报包
void reserve(DatagramPacket p)接收数据报包
DatagramPacket类,数据报包,实现无连接包投递服务,构造方法中,带地址参数的属于接收对象,不带地址参数的属于发送对象。
UDP练习:创建一个dos命令下的聊天小程序并结合多线程
package p;
import java.net.DatagramSocket;
import java.net.SocketException;
public class CharDemo {
public static void main(String[] args) throws SocketException {
// TODO Auto-generated method stub
DatagramSocket send = new DatagramSocket();
DatagramSocket rece = new DatagramSocket(10000);
new Thread(new Send(send)).start();
new Thread(new Rece(rece)).start();
}
}
package p;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Send implements Runnable {
private DatagramSocket ds;
Send(DatagramSocket ds){
this.ds = ds;
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.print("发送端启动...");
//要发送的数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s = null;
try{
while((s=br.readLine())!=null){
byte[] buf = s.getBytes();
//将发送的数据封装成DatagramPacket包
DatagramPacket dp = new DatagramPacket( buf, buf.length, InetAddress.getByName("127.0.0.1"), 10000);
//发送报包
ds.send(dp);
if("886".equals(s))
break;
}
}catch(Exception e){}
}
}
package p;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Rece implements Runnable {
private DatagramSocket ds;
Rece(DatagramSocket ds){
this.ds = ds;
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.print("接收端启动...");
try {
while(true){
//创建报包储存接收到的数据
byte[] buf = new byte[1024];
DatagramPacket ap = new DatagramPacket(buf, buf.length);
//接收数据
ds.receive(ap);
//报包解析数据
String str = ap.getAddress().getHostAddress();
int port = ap.getPort();
String s = new String(ap.getData(),0,ap.getLength());
System.out.println(str+":"+port+":"+s);
if("886".equals(s))
System.out.println(str+"......退出");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
TCP传输
客户端使用Socket类,此类实现客户端套接字,初始化时直接构造地址和端口。Socket流是底层建立好的,既有输入又有输出,想要输入和输出对象,可以用Socket类中的getOutputStream和getInputStream两个方法来实现。
Tcp传输,客户端建立的过程。
1,创建tcp客户端socket服务。使用的是Socket对象。建议该对象一创建就明确目的地。要连接的主机。
2,如果连接建立成功,说明数据传输通道已建立。该通道就是socket流 ,是底层建立好的。 既然是流,说明这里既有输入,又有输出。想要输入或者输出流对象,可以找Socket来获取。 可以通过getOutputStream(),和getInputStream()来获取两个字节流。
3,使用输出流,将数据写出。
4,关闭资源。
服务端使用ServerSocket类,此类实现服务端套接字
服务端接收客户端发送过来的数据,并打印在控制台上。
建立tcp服务端的思路:
1,创建服务端socket服务。通过ServerSocket对象。
2,服务端必须对外提供一个端口,否则客户端无法连接。
3,获取连接过来的客户端对象。
4,通过客户端对象获取socket流读取客户端发来的数据
5,关闭资源。关客户端,关服务端。
由于客户端和服务端中有阻塞方法存在,所以Socket提供了shutdownInput和shutdownOutput方法,用于提示输入输出的结束,让程序跳出循环。
练习:上传文件到服务端
package p3;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 需求:上传文件
* 1、创建客户端Socket
* 2、读取所要上传的文件,源:file
* 目的:Socket
* 3、输出数据,源:Socket
* 目的:服务器端
* 4、关闭资源
* @author Administrator
*
*/
public class UploadClient {
public static void main(String[] args) throws UnknownHostException, IOException {
// TODO Auto-generated method stub
Socket s = new Socket("192.168.1.101",10001);
//创建输入流、输出流
BufferedReader bur = new BufferedReader(new FileReader("G:\\client.txt"));
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
String line = null;
while((line=bur.readLine())!=null){
out.println(line);
}
s.shutdownOutput();
BufferedReader burin = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(burin.readLine());
bur.close();
s.close();
}
}
package p3;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务端接收客户端的数据,储存成文件
* 思路:
* 1、创建服务端Socket,ServerSocket。
* 2、创建客户端对象
* 3、读取客户端对象输出的数据
* 4、储存获得的数据并保存到文件中
* 5、关闭资源
* @author Administrator
*
*/
public class UploadServer {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
ServerSocket ss = new ServerSocket(10001);
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.print(ip + "......connect");
BufferedReader burin = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter burout = new BufferedWriter(new FileWriter("G:\\server.txt"));
String line = null;
while((line=burin.readLine())!=null){
burout.write(line);
burout.flush();
}
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
out.println("上传成功!");
burout.close();
s.close();
ss.close();
}
}
</pre>常见的客户端是浏览器,常见的服务端是服务器。<p></p><p><span style="font-family:arial; font-size:14px; color:#333333"><span style="line-height:20.0200004577637px"><span style="white-space:pre"><span style="color:rgb(51,51,51); font-family:arial; line-height:20.0200004577637px"></span></span></span></span></p><p><span style="font-family:arial; font-size:14px; color:#333333"><span style="line-height:20.0200004577637px"><span style="white-space:pre"><span style="color:rgb(51,51,51); font-family:arial; line-height:20.0200004577637px">浏览器和服务器之间的通信是通过URL来操作的。</span></span></span></span></p><p><span style="font-family:arial; font-size:14px; color:#333333"><span style="line-height:20.0200004577637px"><span style="white-space:pre"><span style="color:rgb(51,51,51); font-family:arial; line-height:20.0200004577637px">类<code>URL</code> 代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。</span></span></span></span></p><p><span style="font-family:arial; font-size:14px; color:#333333"><span style="line-height:20.0200004577637px"><span style="white-space:pre"><span style="color:rgb(51,51,51); font-family:arial; line-height:20.0200004577637px">通过URL的openConnection方法可以获得一个URLConnection对象,这个是获取URL对象的URL连接器对象,将连接封装成对象:Java中内置的可以解析具体协议的对象加Socket。</span></span></span></span></p><p><span style="font-family:arial; font-size:14px; color:#333333"><span style="line-height:20.0200004577637px"><span style="white-space:pre"><span style="color:rgb(51,51,51); font-family:arial; line-height:20.0200004577637px">通过该对象的getInputStream和getOutputStram方法可以获得输入输出字节流,可以通过流对象获取浏览器和服务器之间的数据。</span></span></span></span></p><p><span style="font-family:arial; font-size:14px; color:#333333"><span style="line-height:20.0200004577637px"><span style="white-space:pre"><span style="color:rgb(51,51,51); font-family:arial; line-height:20.0200004577637px"></span></span></span></span></p><p><span style="font-family:arial; font-size:14px; color:#333333"><span style="line-height:20.0200004577637px"><span style="white-space:pre"><span style="color:rgb(51,51,51); font-family:arial; line-height:20.0200004577637px">自定义服务器练习</span></span></span></span></p><p><span style="font-family:arial; font-size:14px; color:#333333"><span style="line-height:20.0200004577637px"><span style="white-space:pre"><span style="color:rgb(51,51,51); font-family:arial; line-height:20.0200004577637px"></span></span></span></span></p><pre name="code" class="java">package p3;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
ServerSocket ss = new ServerSocket(9090);
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + ".......connect!");
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.print(new String(buf,0,len));
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
out.println("hello world!");
s.close();
ss.close();
}
}
运行结果
自定义浏览器练习
package p3;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class MyBrowser {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String str_url = "https://www.baidu.com/";
URL url = new URL(str_url);
URLConnection conn = url.openConnection();
InputStream in = conn.getInputStream();
byte[] buf = new byte[1024];
int len = 0;
while((len = in.read(buf))!=-1)
System.out.print(new String(buf,0,len));
}
}
运行结果
网络结构
1、C/S Slient/Server
特点:该结构的软件,客户端和服务端都需要编写,开发成本较高,维护较为麻烦。
好处:客户端在本地可以分担一部分运算。
2、B/SBrowser/Server
特点:该结构的软件只开发服务端,不开发客户端,因为客户端直接有浏览器代替,开发成本相对较低,维护更简单。
缺点:所有运算都要在服务端完成。