一、网络架构模型主要有OSO参考模型和TCP/IP五层模型:
1.OSI (Open System Interconnect) 参考模型
开放式系统互联,一般叫OSI参考模型。
ISO 是国际标准化组织,1985研究网络互联模型。ISO 为了更好的使用网络、普及,推出了OSI参考模型,让所有的公司按照统一的标准,制定自己的网络,便于互联。
OSI 定义了网络连接的七层框架(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层)。
2.TCP/IP 五层协议
(物理层、数据链路层、网络层、传输层、应用层)
应用层: 应用层是最靠近用户的一层,是为计算机用户提供应用接口,也为用户直接提供各种网络服务,我们常见的网络协议:HTTP、HTTPS、FTP、TELNT等。
传输层: 建立了主机端的链接、传输层的主要作用是为上层协议提供可靠、透明的数据传输服务,包括处理差错控制和流量控制等等问题,使高层用户看到只是两个传输实体的一条主机到主机,可由用户控制和设定 : TCP和UDP就是在这一层。端口号就是这里的“端”。
网络层: 通过IP寻地来建立两个节点之间的链接,为源端的运输层来分组,选择合适的路由和交换节点,正确无误的按照地址传送, 给目的端的运输层,就是通过说的IP层,也是经常说的IP协议层、IP协议是 internet 基础。
二、TCP 协议 与 UDP协议
1.TCP(Tranfer Control Protocol):
是一种面向连接的保证可靠传输的协议,通过TCP协议传输,得到一个顺序无差错的数据流,发送方和接收方成对的两个socket之间必须连接连接,当一个socket 等待连接时,另一个 socket可以要求进行连接,一旦两个socket连接起来,它们就可以进行双向的数据传输,双方都可以进行发送和接收。
TCP的三次握手(建立起来一个TCP连接需要经过三次握手):
第一次:客户端发送syn包到 服务器,并进入SUN_SEND状态,等待服务器确认;
第二次:服务器接收到syn包,必须确认客户端的SYN,同时自己 也发送一个SYN包,此时服务器 进入SYN_RECV状态;
第三次:客户端收到服务器的SYN包,向服务器发送确认,此包发送完毕,客户端和服务器端进入ESTABLISHED状态。 三次握手完成。
握手过程中传送的包中不包含数据,三次握手完毕后,客户端与故武器端才正式的开始传输数据。在理想状态下,TCP连接一旦建立,在通信双方任何一方主动关闭连接之前,TCP连接都将一致保持下去。服务器和客户端都可以主动的断开TCP连接的请求。
2.UDP(User Datagram Protocol):
是一种无连接协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,在网络以任何可能的路径传往目的地址,因此能否到达的地,到达目的地址的时间以及内容的正确性都是不能被保证。
UDP 每个数据报中都给出了完成的地址信息,因此无需建立发送方和接收方的链接,UDP在传输数据的大小上是有所限制的,每个被传输的数据必须限定在60KB之内。
UDP是一个不可靠的协议,发送方所发送的数据并不一定以相同的次序发送到接收方。
3.TCP 面向连接协议:
在socket之间进行数据的传输之前必须连接连接,所以TCP中需要连接时间。
TCP传输数据没有大小的限制,一旦连接建立起来,双方的Socket就可以按照统一的格式传输大的数据。 TCP是可靠的协议它确保接收方完全正确的获取发送方所发送的全部数据。
TCP在网络通信上有极强的生命力的。如远程连接(TeLnet) 和 文件的传输(FTP) 都需要不定长度数据被可靠的传输,但是可靠的传输,需要付出代价,对数据的内容中正确性的检验必然需要占用计算的处理时间和网络宽带,所以TCp传输的效率不如UDP高。
4. UDP
操作简单,而且仅需要少量的监护,所以通常用于局域网高可靠性的分散系统中,比如视频会议。
5.Socket 原理
Socket提供了进程通信的端点,进程通信之前,双方首相必须各自创建一个端点否则没有办法连接相互通信。
步骤:连接过程 — 服务器监 — 客户端的请求 — 连接的确认。
三、应用
1.服务器端与客户端
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
BufferedReader br = null;
try {
// 建立一个服务器Socket 指定端口并开始监听
serverSocket = new ServerSocket(8800);
// 使用 accept()方法 等待客户端触发通信
socket = serverSocket.accept();
//打开 输入输出流
is = socket.getInputStream();
// 获取客户端的信息,从输入流中读取信息
br = new BufferedReader(new InputStreamReader(is));
String info = null;
//循环读取
while ((info = br.readLine()) != null) {
System.out.println("我是服务器端:"+info);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != br)
br.close();
if (null != is)
is.close();
if (null != socket)
socket.close();
if (null != serverSocket)
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
try {
// 建立客户端的Socket连接,指定服务器的位置和端口
socket = new Socket("localhost", 8800);
os = socket.getOutputStream();
String info = "我是客户端:内容测试";
//发送
os.write(info.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != os)
os.close();
if (null != socket)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.服务器端与客户端相互通讯
serverSocket = new ServerSocket(8801);
// 等待客户端 通信
socket = serverSocket.accept();
is = socket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
User user = (User) ois.readObject();
System.out.println("我是服务器:接收到的信息:"+user.getUserCode()+"-"+user.getUserPwd());
//给客户端一个回音
String reply = "欢迎登录";
os = socket.getOutputStream();
os.write(reply.getBytes());
socket = new Socket("localhost", 8801);
os = socket.getOutputStream();
User user = new User("admin", "123456");
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(user);
socket.shutdownOutput();
//通过输入流来接收服务器端 给客户端的响应
is = socket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String reply = "";
while ((reply = br.readLine()) != null) {
System.out.println("服务器的响应:" + reply);
}
3. 与线程的应用
public class DemoA extends Thread {
private Socket socket = null;
public DemoA(Socket socket) {
this.socket = socket;
}
// 启动线程 响应客户端请求
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
ObjectInputStream ois = new ObjectInputStream(is);
//获取客户端信息
// BufferedReader br = new BufferedReader(new InputStreamReader(ois));
User user = (User) ois.readObject();
if (null != user) {
System.out.println("我是服务器端:" + user.getUserCode()+"------"+user.getUserPwd());
}
// 给客户端一个响应
os.write(("欢迎"+user.getUserCode()+",登录成功").getBytes());
ois.close();
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public class DemoAServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8802);
// serverSocket.accept();
Socket socket = null;
while (true){
// 再循环中 使用 accept 方法 等待客户端触发通信
socket = serverSocket.accept();
DemoA demoA = new DemoA(socket);
demoA.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class DemoAClient {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
InputStream is = null;
BufferedReader br = null;
ObjectOutputStream oos = null;
try {
socket = new Socket("192.168.8.112", 8802);
os = socket.getOutputStream();
is = socket.getInputStream();
oos = new ObjectOutputStream(os);
User user = new User("lisi", "admin");
oos.writeObject(user);
socket.shutdownOutput();
br = new BufferedReader(new InputStreamReader(is));
String reply = "";
while ((reply = br.readLine()) != null) {
System.out.println(reply);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != br)
br.close();
if (null != oos)
oos.close();
if (null != is)
is.close();
if (null != os)
os.close();
if (null != socket)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.UDP的通讯方式
public class DemoA {
public static void main(String[] args) {
DatagramSocket socket = null;
byte[] infos = new byte[1024];
DatagramPacket dp = new DatagramPacket(infos, infos.length);
try {
socket = new DatagramSocket(8003);
// 接收到客户端的数据包 并将信息封装到DatagramPacket 对象中
socket.receive(dp);
//构建一个字符串
String info = new String(dp.getData(), 0, dp.getData().length);
System.out.println("客户端说:" + info);
//给客户端一个响应
// 客户端的地址
SocketAddress sa = dp.getSocketAddress();
String strs = "您好 我是服务器端!";
DatagramPacket dpA = new DatagramPacket(strs.getBytes(), 0, strs.getBytes().length, sa);
socket.send(dpA);
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != socket)
socket.close();
}
}
}
public class DemoB {
public static void main(String[] args) {
String info = "你好 我想咨询一个问题!";
byte[] infos = info.getBytes();
DatagramSocket socket = null;
try {
// 客户端需要一个 DatagramSocket 对象
socket = new DatagramSocket();
InetAddress ia = InetAddress.getByName("localhost");
// 构建客户端需要 发送的数据包对象
DatagramPacket dp = new DatagramPacket(infos,infos.length,ia,8003);
socket.send(dp);
byte[] strs = new byte[1024];
DatagramPacket dp1 = new DatagramPacket(strs, strs.length);
socket.receive(dp1);
String reply = new String(dp1.getData(),0,dp1.getData().length);
System.out.println(reply);
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(null != socket){
socket.close();
}
}
}
}