概述
-
网络编程中有两个主要的问题:
- 如何准确地位网络上一台或多台主机;定位主机上的特定应用
- 找到主机后如何可靠高效地进行数据传输
网络通信要素
-
网络编程中的两个要素
- 对应问题一:IP和端口号
- 对应问题二:提供网络通信协议:TCP/IP参考模型(应用层(应用层+表示层+会话层)、传输层、网络层、数据链路层(物理层+数据链路层))
IP
- 唯一定位一台网络上计算机
- 在Java中使用InetAddress类代表IP
- 本机地址:127.0.0.1 <=> localhost
- InetAddress类没有提供公共的构造器,而是提供了如下几个静态方法来获取 InetAddress实例
- getByName(String host)
- getLocalHost()
- 常用方法
- getHostName() //域名
- getHostAddress() //ip
- public boolean isReachable(int timeout) //测试是否可以达到该地址
端口
-
标识正在计算机上运行的进程(程序)
-
不同进程有不同的端口号,用来区分软件
-
规定为一个16位的整数 0~65535
-
单个协议下,端口号不能冲突
-
端口分类
-
公有端口 0~1023
- HTTP:80
- HTTPS:443
- FTP:21
- Telent:23
-
程序注册端口:1024~49151,分配用户或程序
- Tomcat:8080
- MySQL:3306
- Oracle:1521
-
动态、私有:49152~65535
netstat -ano #查看所有的端口 netstat -ano|findstr "5900" #查看指定端口 tasklist|findstr "8696" #查看指定端口的进程
-
-
端口号与IP地址的组合得出一个网络套接字:Socket
通信协议
协议:约定,就好比我们现在说的普通话。
网络通信协议:速率,传输码率,代码结构,传输控制……
TCP/IP协议簇:实际上是一组协议
重要:
- TCP:用户传输协议
- UDP:用户数据报协议
出名的协议:
- TCP:
- IP:网络互连协议
TCP UDP 对比
-
TCP协议编程:打电话
- 连接,可靠的数据传输(
三次握手
四次挥手
);进行大数据量传输;传输完成,释放连接,效率低
- 连接,可靠的数据传输(
-
UDP协议编程:发短信
- 不连接,不可靠;以数据报形式发送,数据报限定64k;不管有没有准备好,都可以发给你,效率高
- 导弹
TCP
-
客户端发送信息给服务器,服务器将数据显示在控制台
客户端:
- 连接服务器Socket
- 发送消息
Socket socket = null; OutputStream os = null; try { //1.创建Socket对象,指明服务器端的ip和端口号 InetAddress inet = InetAddress.getByName("127.0.0.1"); int port = 8899; //2.创建一个socket连接 socket = new Socket(inet,port); //3.获取一个输出流,用于输出数据 发送消息 os = socket.getOutputStream(); // fis = new FileInputStream(new File("day02\\hello.txt")); // byte[] c = new byte[1024]; // int len; // while ((len =fis.read(c)) != -1){ // os.write(c,0,len); // } //写出数据的操作 os.write("你好,我是客户端mm".getBytes()); } catch (IOException e) { e.printStackTrace(); }finally { if (os != null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
服务器端:
- 建立服务器的端口ServerSocket
- 等待用户的链接accept
- 接受用户的消息
ServerSocket ss = null; Socket socket = null; InputStream is = null; ByteArrayOutputStream baos = null; try { //1.创建服务器端的SeverSocket,指明自己的端口号 ss = new ServerSocket(8899); //2.调用accept()表示接受来自于客户端的信息 socket = ss.accept(); //3.获取输入流 读取客户端的消息 is = socket.getInputStream(); // new FileOutputStream(new File("day02\\1.txt")); // byte[] b = new byte[1024]; // int len; // while ((len = is.read(b)) != -1){ // fos.write(b,0,len); // } //管道流 baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = is.read(buffer)) != -1){ baos.write(buffer,0,len); } System.out.println(baos.toString()); } catch (IOException e) { e.printStackTrace(); }finally { //关闭资源 baos.close(); is.close(); socket.close(); ss.close(); } }
文件上传
客户端
package com.sdyu.socket;
import java.io.*;
import java.net.Socket;
/**
* 客户端:发送文件给服务器端
* @author ht
* @date 2021/2/20
**/
public class Client01 {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 9090);
OutputStream os = socket.getOutputStream();
FileInputStream fis = new FileInputStream(new File("day01\\1.txt"));
byte[] buffer = new byte[1024];
int len = 0;
while ((len = fis.read(buffer)) != -1){
os.write(buffer,0,len);
}
//通知服务器,我已经结束了
socket.shutdownOutput();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = socket.getInputStream();
byte[] buffer2 = new byte[2014];
int len2 = 0;
while ((len2 = is.read(buffer2)) !=-1 ) {
baos.write(buffer2,0,len2);
}
System.out.println(baos.toString());
is.close();
baos.close();
fis.close();
os.close();
socket.close();
}
}
服务器端
package com.sdyu.socket;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务器端:将文件保存在本地,并返回”发送成功“给客户端
* @author ht
* @date 2021/2/20
**/
public class Server01 {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(9090);
Socket accept = ss.accept();
InputStream is = accept.getInputStream();
FileOutputStream pos = new FileOutputStream(new File("3.txt"));
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1) {
pos.write(buffer,0,len);
}
OutputStream os = accept.getOutputStream();
os.write("发送成功!".getBytes());
os.close();
pos.close();
is.close();
accept.close();
ss.close();
}
}
Tomcat
客户端:
- 自定义 C
- 浏览器 B
服务器端:
- 自定义 S
- Tomcat服务器 S java后台开发
UDP
发短信:不用连接,需要知道对方的地址!
发送消息
发送端
package com.sdyu.socket;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* @author ht
* @date 2021/2/20
**/
public class UdpClientTest01 {
public static void main(String[] args) throws Exception {
//1.建立一个Socket
DatagramSocket socket = new DatagramSocket();
//2.建包
String msg = "你好啊,服务器!";
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9090;
DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,9090);
//3.发送包
socket.send(packet);
//4.关闭流
socket.close();
}
}
接收端
package com.sdyu.socket;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* @author ht
* @date 2021/2/20
**/
public class UdpServerTest01 {
public static void main(String[] args) throws Exception {
//开放端口
DatagramSocket socket = new DatagramSocket(9090);
//接收数据包
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
socket.receive(packet); //阻塞接收
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(),0,packet.getLength()));
//关闭连接
socket.close();
}
}
循环发送消息
package com.sdyu.socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
/**
* @author ht
* @date 2021/2/20
**/
public class UdpSentDemo01 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8000);
//准备数据:控制台读取 System.in
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666));
socket.send(packet);
if (data.equals("bye")) {
break;
}
}
socket.close();
}
}
循环接收消息
package com.sdyu.socket;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* @author ht
* @date 2021/2/20
**/
public class UdpReceiveDemo01 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
while (true) {
//准备接收包裹
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
socket.receive(packet);
//断开连接
byte[] data = packet.getData();
String receiveData = new String(data, 0, data.length);
System.out.println(receiveData);
if (receiveData.equals("byte")) {
break;
}
}
socket.close();
}
}
URL
-
<传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表
-
URL编程
//1.下载地址 URL url = new URL("http://192.168.14.1000:8080/examples/hello.txt?username=Tom "); //2.连接到这个资源 HTTP HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection(); InputStream is = urlConnection.getInputStream(); FileOutputStream fileOutputStream = new FileOutputStream("2.txt"); byte[] buffer = new byte[1024]; int len = 0; while ((len = is.read(buffer)) != -1) { fileOutputStream.write(buffer,0,len); } fileOutputStream.close(); is.close(); urlConnection.disconnect();//断开连接