目录
一、网络基础知识
计算机网络
计算机网络,就是把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,共享硬件、软件、数据信息等资源。
网络体系结构
网络体系结构定义计算机设备和其他设备如何连接在一起以形成-一个允许用户共享信息和资源的通信系统。
国际标准化组织ISO于1978年提出“开放系统互连参考模型”,即著名的OSI (Open System
Interconnection)模型。OSI模型保证了各类设备生产厂家的产品兼容性。
该模型把计算机网络分成物理层、数据链路层、网络层、传输层、会话层、表示层、应用
层等七层。
OSI模型分层好处
不同厂商生产的设备都可以相互兼容。
设备可以专注于某一层的功能,如果交换机工作在第二层,路由器工作在第三层。
方便网络故障排错。
不用过多考虑物理接口等这些物理层的东西。
提供应用程序间通信 | 7 | 应用层 |
处理数据格式、数据加密等 | 6 | 表示层 |
建立、维护和管理会话 | 5 | 会话层 |
建立主机端到端连接 | 4 | 传输层 |
寻址和路由选择 | 3 | 网络层 |
提供介质访问、链路管理等 | 2 | 数据链路层 |
比特流传输 | 1 | 物理层 |
OSI参考模型中数据分装过程
TCP/IP
TCP/IP是一组用于实现网络互连的通信协议。Internet网络 体系结构以TCP/IP为核心。基于TCP/IP的参考模型将协议分成四个层次,它们分别是:网络接口层、网络层、传输层、和应用层。
OSI层次 | TCP/IP层次 | TCP/IP协议集 | ||||
5~7层 | 应用层 | SMTP | DNS | FTP | RPC | SNMP |
4层 | 传输层 | TCP | UDP | |||
3层 | 网络层 | IP(ICMPAPP.RARP) | ||||
1~2层 | 网络接口层 | Ethemet | Token-Eing | 100BASE-T | Others |
网络编程的目的
网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通讯。网络编程中有两个主要的问题,一个是如何准确的定位网络上一-台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输。
网络通讯要素
IP地址
网络中每台主机都必须有一个惟一的IP地址。
因特网上的IP地址具有全球唯一性。
IP地址由32位二进制组成,占4个字节,常用十进制的格式表示,
例如: 192.168.0.5
对应的类-InetAddress
端口号
端口号用来表示该计算机上的应用程序,代表此应用程序逻辑地址。
端口号使用一个16位的数字来表示,它的范围是0~65535,1024以下的端口号保留给预定义的服务。例如: http使用80端口。
协议概念
为计算机网络中进行数据交换而建立的规则、标准或约定的集合。
常见的传输协议
TCP是Tranfer Control Protocol的简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。
UDP是User Datagram Protocol的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络.上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。
二、Socket编程
目前较为流行的网络编程模型是客户机/服务器通信模式
客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求。如图所示,通常,一个服务器进程会同时为多个客户进程服务,图中服务器进程B1同时为客户进程A1、A2和B2提供服务
Socket概念
1.所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。
2.应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
3.Socket是连接运行在网络上的两个程序间的双向通讯的端点。网络通讯其实指的就是Socket间的通讯。
4.通讯的两端都有Socket,数据在两个Socket之间通过I0来进行传输。
使用Socket进行网络通信的过程
1.服务器程序将一个套接字绑定到一个特定的端口,并通过此套接字等待和监听客卢的连接请求
2.客户程序根据服务器程序所在的主机名和端口号发出连接请求。
3.如果一切正常,服务器接受连接请求。并获得一个新的绑定到不同端口地址的套接字。
4.客户和服务器通过读、写套接字进行通讯。
基于TCP协议的Socket编程
创建TCP客户端步骤
1.创建一个Socket对象
2.从Socket中获取I/O流
3.对I/O流进行读写操作,完成与服务端的交互。
4.关闭I/O流和Socket
创建TCP服务端步骤
1.创建一个ServerSocket对象
2.调用accept()方法接受客户端请求
3.从Socket中获取I/O流
4.对I/O流进行读写操作,完成与客户端的交互。
强调:客户端和服务端进行数据传输时,客户端的输入流对服务端的输出流,客户端的输出流对应服务端的输入流
package com.zsl.socket;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Locale;
public class TCPServer {
public static void main(String[] args) throws Exception {
/*客户端*/
/*1、创建一个socketServer对象*/
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("我是服务端:");
/*2、调用accept()方法来接收客户端请求*/
Socket socket = serverSocket.accept();
/*3、调用sockt的输入和输出流*/
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));/*获取输入流*/
/*BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));*//*获取输出流*/
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
/*服务端接收客户端信息返回给客户端大写*/
/*服务端读取客户端信息*/
String line = null;
while ((line = bufferedReader.readLine()) != null){
/*当客户端输入为OVER时服务端终止*/
if ( line.equals("over")){
break;
}
System.out.println(line);
/*将服务端数据写回给客户端 .toUpperCase()转化为大写*/
/*bufferedWriter.write(line.toUpperCase());
bufferedWriter.newLine();
bufferedWriter.flush();*//*刷新数据*/
printWriter.println(line.toUpperCase());/*println()方法代替newLine()和write()方法*/
printWriter.flush();
}
/* bufferedWriter.close();*/
printWriter.close();
bufferedReader.close();
socket.close();
}
}
package com.zsl.socket;
import java.io.*;
import java.net.Socket;
import java.util.Locale;
public class TCPClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("192.168.0.6", 8888);
System.out.println("我是客户端");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));/*获取输入流---->从键盘输入*/
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));/*获取输出流*/
BufferedReader readerbufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));/*服务端传输的数据*/
/*往服务端写数据*/
while (true){
String line = bufferedReader.readLine();/*获取键盘输入的字符串*/
bufferedWriter.write(line);
bufferedWriter.newLine();
bufferedWriter.flush();
if (line.equals("over")) {
break;
}
System.out.println(readerbufferedReader.readLine());/*打印服务端传输的数据*/
}
readerbufferedReader.close();
bufferedWriter.close();
bufferedReader.close();
socket.close();
}
}
基于UDP协议的Socket
创建发送端
1.建立DatagramSocket对象。该端点建立,系统会随机分配一个端口。
如果不想随机配置,可以手动指定。
2.将数据进行packet包的封装,必须要指定目的地地址和端口。
3通过socket服务的send方法将该包发出。
4.将socket关闭。
创建接受端
1.建立DatagramSocket对象。要监听一个端口。
2.通过socket的receive方法将数据存入数据包中。
3.通过数据包dp的方法getData()、getAddress()、 getPort()等方法
package com.zsl.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/*发送端*/
public class UDPDemo1 {
public static void main(String[] args) throws Exception {
/*可以指定端口,也可以不指定端口,端口会随机分配*/
var datagramSocket = new DatagramSocket();
String str = "I love Java";
/*对数据封装,封装到数据包中*/
var localhost = new DatagramPacket(str.getBytes(), str.length(), InetAddress.getByName("localhost"), 8000);/*InetAddress.getByName("localhost")本机地址*/
/*发送localhost包*/
datagramSocket.send(localhost);
/*接收接收端数据*/
var bytes = new byte[100];
var datagramPacket = new DatagramPacket(bytes, 100);
datagramSocket.receive(datagramPacket);
System.out.println(new String(bytes,0,datagramPacket.getLength()));
datagramSocket.close();
}
}
package com.zsl.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*接受端*/
public class UDPDemo2 {
public static void main(String[] args) throws Exception {
/*先收在发*/
/*指定端口 8000*/
var datagramSocket = new DatagramSocket(8000);
/*接收消息*/
var bytes = new byte[100];
var datagramPacket = new DatagramPacket(bytes, 100);
datagramSocket.receive(datagramPacket);
System.out.println(new String(bytes,0,datagramPacket.getLength()));
/*返回消息*/
String str = "Me Took!";
/*对数据封装,封装到数据包中*/
var localhost = new DatagramPacket(str.getBytes(), str.length(), datagramPacket.getAddress(),datagramPacket.getPort());/*InetAddress.getByName("localhost")本机地址*/
/*发送localhost包*/
datagramSocket.send(localhost);
/*接收接收端数据*/
datagramSocket.close();
}
}
URL编程
URL概念
什么是URL
URL(Uniform Resource Locator)是一致 资源定位器的简称,它表示Internet上某一资源的地址。通过URL我们可以访问Internet上的各种网络资源,比如最常见的WWW,FTP站点。浏览器通过解析给定的URL可以在网络上查找相应的文件或其他资源。
URL的基本结构由5部分组成
<传输协议>://<主机名>:<端口号>/<文件名>#<引用>
http://www.tomcat.com:80/Gamelan/network. .htm#BOTTOM协议名://机器名+端口号+文件名+内部引用
获取URL对象的属性
getFile():获得URL指定资源的完整文件名。
getHost():返回主机名 。
getPath():返回指定资源的文件目录和文件名。
getPort():返回端口号
getProtocol():返 回表示URL中协议的字符串对象。
getRef():返回URL中的HTML文档标记,即#号标记。
getUserInfo:返回用户信息。
URL有两种方法可以用来访问Internet上资源
1、使用URL的openConnection()方法创建一个URLConnection类的对象。 再通过
URLConnection对象获取相应输入流和输出流。
2、利用URL类的openStream()方法。openStream()方 法与指定的URL建立连接
并返回InputStream类的对象。
package com.zsl.url;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class URLDemo {
public static void main(String[] args) throws Exception {
DownLoadUtil.download("https://www.baidu.com/img/PCfb_5bf082d29588c07f842ccde3f97243ea.png","baidu_logo.png","C:\\Users\\CCC\\Desktop");
}
}
class DownLoadUtil{
/**
* urlString -->网络资源路径
* fileName -->文件保存路径
* savaPath -->文件保存的路径
* */
public static void download(String urlString,String fileName,String savaPath) throws Exception {
var url = new URL(urlString);
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
byte[] buff = new byte[1024];
int line = 0;
File file = new File(savaPath);
/*文件是否存在*/
if (!file.exists()){
file.mkdirs();
}
System.out.println("路径为:"+file.getAbsolutePath()+"\\"+fileName);
/*网络资源写入相应的文件*/
FileOutputStream fileOutputStream = new FileOutputStream(file.getAbsolutePath() + "\\" + fileName);
while ((line = inputStream.read()) != -1){
fileOutputStream.write(buff,0,line);
}
fileOutputStream.close();
inputStream.close();
}
}
TCP多客户端连接案例:
package comtext.demo;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/*服务端*/
public class ChatServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
int number = 1;/*保存客户端的数量*/
/*死循环,不停的检测客户端,有一个客户端就开一个线程*/
while (true) {
Socket socket = serverSocket.accept();/*拿去客户端*/
System.out.println("客户端:" + number + "已连接");
/*服务器开启一个独立的线程来对客户端进行读写*/
new Thread(new ServerStream(socket,number)).start();
number++;
}
}
}
package comtext.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Locale;
/*服务端线程*/
public class ServerStream implements Runnable{
private Socket socket = null;
private int number;
public ServerStream(Socket socket, int number) {
this.socket = socket;
this.number = number;
}
@Override
public void run() {
/*把客户端传过来的消息返回成大写的回去*/
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);
while (true) {
String line = br.readLine();
System.out.println("客户端" + number + ":" + line);
pw.println(line.toUpperCase(Locale.ROOT));
if (line.equals("bye")) {
System.out.println("客户端" + number + "已断开连接");
break;
}
}
br.close();
pw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package comtext.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/*客户端输出流*/
public class ClientOutputStream implements Runnable{
private Socket socket = null;
public ClientOutputStream(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));/*传进来键盘输入*/
PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);/*输出*/
while (true) {
String line = br.readLine();
pw.println(line);
if (line.equals("bye")) {
break;
}
}
br.close();
pw.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package comtext.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/*客户端输入流*/
public class ClientInputStream implements Runnable{
private Socket socket = null;
public ClientInputStream(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));/*传进来键盘输入*/
PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);/*输出*/
try {
while (true) {
String line = br.readLine();
System.out.println(line);
}
} catch (IOException e) {
br.close();
pw.close();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package comtext.demo;
import java.io.IOException;
import java.net.Socket;
/*客户端入口*/
public class ChatClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.0.6", 8888);
new Thread(new ClientInputStream(socket)).start();
new Thread(new ClientOutputStream(socket)).start();
}
}