文章目录
一、网络编程中的两个主要问题
- 如何准确定位网络上的一台或多态主机:如何定位主机上的特定的应用
- 找到主机后如何进行高高效可靠的数据传输
二、通信要素一——IP和端口号
IP:设备在网络中的地址,唯一标识
IP分为IPV4(32位)和IPV6(128位,冒分十六进制表示法)
端口号(0~65535):用于标识计算机上运行的进程(程序),区分应用程序
公认端口:
注册端口:
动态/私有端口:
IP+端口号 ===> Socket套接字
2.1、InetAddress类
2.1.1 InetAddress实例化
getByName(String host)
,getLocalHost()
。
try {
//获取本机地址
System.out.println(InetAddress.getLocalHost());
InetAddress inet1 = InetAddress.getByName("localhost");
System.out.println(inet1);
//通过域名获取地址
InetAddress inet2 = InetAddress.getByName("www.baidu.com");
System.out.println(inet2);
InetAddress inet3 = InetAddress.getByName("196.168.10.14");
System.out.println(inet3);
} catch (UnknownHostException e) {
e.printStackTrace();
}
输出:
WRGHO-20210121P/192.168.31.160
localhost/127.0.0.1
www.baidu.com/14.215.177.39
/196.168.10.14
2.1.2 InetAddress的两个常用方法
getHostName()
:获取域名
getHostAddress
:获取主机地址IP
InetAddress inet2 = InetAddress.getByName("www.baidu.com");
System.out.println(inet2);// www.baidu.com/14.215.177.38
System.out.println(inet2.getHostName());
System.out.println(inet2.getHostAddress());
输出:
www.baidu.com/14.215.177.38
www.baidu.com
14.215.177.38
三、通信要素二——网络协议
3.1 概念理解
- 网络协议指的是计算机网络中互相通信的对等实体之间交换信息时所必须遵守的规则的集合。对传输代码,代码结构,传输控制步骤,出错控制等指定标准
- 通信协议的分层思想:同层之间可通行、上一层可以调用下一层,中间有隔层的层之间不发生关系。各层之间互不影响
3.2传输层中的两个重要协议TCP/UDP
TCP协议 | UDP协议 |
---|---|
使用TCP前,需先建立TCP连接,形成传输数据通道 | 将数据、源、目的封装成数据包,不需要建立连接 |
传输前采用”三次握手“方式,点对点通信,是可靠的 | 每个数据报的大小限制在64k内 |
TCP协议进行通信的两个应用进程:客户端、服务器端 | 发送不管对方是否准备好,接收方也不确认,故是不可靠的 |
在连接中可进行大数据量的传输 | 可以广播发送 |
传输完毕,释放已建立的连接藕、 | 发送数据结束时无需释放资源,开销小,速度低 |
3.2.1 TCP 网络编程(Transmission Control Protocol)
三次握手
四次挥手
模拟客户端代码:
//模拟客户端
public void client() {
Socket socket = null;
OutputStream os = null;
try {
//1、创建socket对象,指明服务器端的ip和端口号
InetAddress serverID = InetAddress.getByName("192.168.31.160");
socket = new Socket(serverID,8899);
//2、获取输出流用于输出数据
os = socket.getOutputStream();
//3、用输出流写出数据
os.write("Hello,我是客户端!".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、资源关闭
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
模拟服务器端代码:
public void server() {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
//1、创建服务器端socket:ServerSocket指明自己的端口号
serverSocket = new ServerSocket(8899);
//2、调用accept接受来自客户端的socket
socket = serverSocket.accept();
//3、获取输入流
is = socket.getInputStream();
//4、读取输入流中的数据
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[5];
int len;
while ((len = is.read(buffer)) != -1){
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
//查看发送端地址和ip
System.out.println(socket.getInetAddress().getHostAddress());
} catch (IOException e) {
e.printStackTrace();
} finally {
//5、关闭资源
if (baos != null ) {
try {
baos.close();
is.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
例题
题目:客户端发送文件给服务器端,服务器端保存到本地,服务器返回信息给客户端
客户端:
public void client() {
Socket socket = null;
OutputStream outputStream = null;
BufferedInputStream bis = null;
ByteArrayOutputStream baos = null;
try {
//1、创建套接字,指明服务ip,和端口号
InetAddress inetAddress = InetAddress.getByName("192.168.31.160");
socket = new Socket(inetAddress, 8899);
//2、获取输出流
outputStream = socket.getOutputStream();
//3、提供要发送的文件
bis = new BufferedInputStream(new FileInputStream("皮卡丘.jpg"));
//4、输出流发送文件
int len;
byte[] buffer = new byte[1024];
while ((len = bis.read(buffer)) != -1){//read是一种阻塞的方法
outputStream.write(buffer);
}
//关闭数据输出
socket.shutdownOutput();
//5、接收来自服务器端的数据,并显示到控制台上
InputStream is = socket.getInputStream();
baos = new ByteArrayOutputStream();
byte[] buffer1 = new byte[20];
int len1;
while ((len1 = is.read(buffer1)) != -1){
baos.write(buffer1,0,len1);
}
System.out.println(baos);
} catch (IOException e) {
e.printStackTrace();
} finally {
//6、关闭流
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器端:
public void server(){
Socket socket = null;
InputStream inputStream = null;
BufferedOutputStream bos = null;
OutputStream outputStream = null;
try {
//1、创建ServerSocket指明端口号
ServerSocket serverSocket = new ServerSocket(8899);
//2、调用accept接收socket
socket = serverSocket.accept();
//3、获取输入流
inputStream = socket.getInputStream();
//4、造输出流
bos = new BufferedOutputStream(new FileOutputStream("皮卡丘TCP传输.jpg"));
//5、获取socket中的数据
int len;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1){
bos.write(buffer,0,len);
}
System.out.println("图片传输完成");
//6、服务器端给予客户端反馈
//6.1提供输出流
outputStream = socket.getOutputStream();
outputStream.write("文件发送成功!".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//7、关闭流
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.2.2 UDP 网络通信(User Datagram Protocol)
UDP模拟cs传输数据
sent:
//发送端
@Test
public void send() throws IOException {
DatagramSocket socket = new DatagramSocket();
//封装数据包
String str = "我是UDP数据报";
byte [] data = str.getBytes();
InetAddress address = InetAddress.getByName("192.168.31.160");
DatagramPacket packet = new DatagramPacket(data,0,data.length,address,9090);//封装数据
socket.send(packet);
socket.close();
}
reciver:
//接收端
@Test
public void reciver() throws IOException {
DatagramSocket socket = new DatagramSocket(9090);
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
socket.receive(packet);
System.out.println(new String(packet.getData(), 0, packet.getLength()));
socket.close();
}
3.3 URL编程
- 同一资源定位符,对应互联网的某一资源地址
- URL的基本结构:
<传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表
URL类常用方法
功能 | 方法 |
---|---|
获取协议名 | getProtocol() |
获取URL主机名 | getHost() |
获取URL端口号 | getPort() |
获取URL文件路径 | getPath() |
获取URL文件名 | getFile() |
获取URL查询名 | getQuery() |
3.3.1 从Tomcat下载资源
步骤图解
代码
public static void main(String[] args){
HttpURLConnection urlConnection = null;
InputStream is = null;
FileOutputStream fos = null;
try {
URL url = new URL("http://127.0.0.1:8080/hello/cat.png");
urlConnection = (HttpURLConnection)url.openConnection();
//获取连接
urlConnection.connect();
//获取流
is = urlConnection.getInputStream();
fos = new FileOutputStream(new File("guigu20210914\\cat_downloadfromTomcat1.png"));
byte buffer[] = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1){
fos.write(buffer,0,len);
}
System.out.println("下载完成!");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
urlConnection.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}