【遇见狂神说】
https://www.bilibili.com/video/BV1LJ411z7vY?spm_id_from=333.999.0.0
计算机网络
计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
通信双方地址:
规则:网络通信的协议
ip地址:InetAddress
public class TestNet {
public static void main(String[] args) {
try {
InetAddress byName = InetAddress.getByName("127.0.0.1");
System.out.println(byName);
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);
InetAddress byName1 = InetAddress.getByName("www.baidu.com");
System.out.println(byName1);
// 常用方法
System.out.println(byName1.getAddress());
System.out.println(byName1.getCanonicalHostName()); // 规范的名字
System.out.println(byName1.getHostAddress()); // 获得主机地址
System.out.println(byName1.getHostName()); // 获得电脑名字
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
结果
/127.0.0.1
xiexuchun/192.168.237.1
www.baidu.com/39.156.66.18
[B@1540e19d
39.156.66.18
39.156.66.18
www.baidu.com
端口表示计算机上的一个程序的进程
netstat -ano # 查看所有端口
netstat -ano|findstr "端口号" # 查看指定的端口
tasklist|findstr "8696" # 查看指定端口的进程
协议:约定,就好比我们说的普通话
网络通信协议:速率,传输码率,代码结构,传输控制…
TCP/IP协议簇,实际上是一组协议
参考百度百科:
https://baike.baidu.com/item/TCP/IP%E5%8D%8F%E8%AE%AE/212915
重要:
TCP的三次握手和四次挥手
1)Client:嘿,李四,是我,听到了吗?
2)Server:我听到了,你能听到我的吗?
3)Client:好的,我们互相都能听到对方的话,我们的通信可以开始了。
1)Client:我所有东西都说完了
2)Server:我已经全部听到了,但是等等我,我还没说完
3)Server:好了,我已经说完了
可以理解为TCP就像是打电话,要确定对方能收到消息。UDP就像是发短信,短信发出去了,但不确定对方人能不能收得到。
// 服务器
public class TcpServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
// 1.我的有一个地址
serverSocket = new ServerSocket(9999);
while (true){
// 2.等待客户端连接 循环监听
socket = serverSocket.accept(); // accept(); 监听
// 3.读取客户端的消息
is = socket.getInputStream();
// 管道流
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 {
if (baos != null){
try {
baos.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 class TcpClient {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
try {
// 1.要知道服务器的地址,端口
InetAddress serverIp = InetAddress.getByName("127.0.0.1");
int port = 9999;
// 2.创建一个Socket连接
socket = new Socket(serverIp,port);
// 3.发送消息,相当于往外写
os = socket.getOutputStream();
String string = "我在学习网络编程...";
os.write(string.getBytes()); // 将字符串打散为字节数组
} catch (Exception 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();
}
}
}
}
}
结论:服务器设置循环监听,启动一次即可。客户端每次发送的内容会被服务器接收打印。
// 服务器
public class TcpServer {
public static void main(String[] args) throws Exception {
// 1.创建服务
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
FileOutputStream fos = null;
serverSocket = new ServerSocket(9980);
// 2.监听客户端的连接
socket = serverSocket.accept();// 阻断式连接,会一直等待客户端连接
// 3.获取输入流
is = socket.getInputStream();
// 4.文件输出
fos = new FileOutputStream(new File("picture1.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
System.out.println("成功接收...");
// 5.通知客户端接收完毕
OutputStream os = socket.getOutputStream();
os.write("我接受到了,你可以关闭了...".getBytes());
// 6.关闭资源
fos.close();
os.close();
is.close();
socket.close();
serverSocket.close();
}
}
// 客户端
public class TcpClient {
public static void main(String[] args) throws Exception {
// 1.创建一个Socket连接
InetAddress serverIp = InetAddress.getByName("127.0.0.1");
int port = 9980;
Socket socket = new Socket(serverIp,port);
// 2.创建一个输出流
OutputStream os = socket.getOutputStream();
// 3.文件流 读取文件
FileInputStream fis = new FileInputStream(new File("picture.jpg"));
// 4.写出文件
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1){
os.write(buffer,0,len);
}
// 5.通知服务器,文件写出结束了
socket.shutdownOutput();
// 6.服务器确定接收后断开服务
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[1024];
int len2;
while ((len2=is.read(buffer2))!=-1){
baos.write(buffer2,0,len2);
}
System.out.println(baos.toString());
// 7.关闭资源
baos.close();
fis.close();
os.close();
is.close();
socket.close();
}
}
发短信:需用连接,但是要知道对方的地址
// 接收端
public class UdpServer {
public static void main(String[] args) throws Exception {
// 开放端口
DatagramSocket socket = new DatagramSocket(2280);
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();
}
}
// 发送端
public class UdpCliect {
public static void main(String[] args) throws Exception {
// 1.建立Socket
DatagramSocket socket = new DatagramSocket();
// 2.建包
String msg = "你好啊,服务器...";
InetAddress localhost = InetAddress.getByName("127.0.0.1");
int port = 2280;
// 数据
DatagramPacket packagt = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
// 3.发送
socket.send(packagt);
// 4.关闭
socket.close();
}
}
结论:UDP没有客户端和服务器的概念,可以互相发送。而TCP只能由客户端往服务器发送。
使用UDP实现发送消息
// 接收端
public class UdpReceive {
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("bye")){
break;
}
}
socket.close();
}
}
// 发送端
public class UdpSender {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
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("127.0.0.1",6666));
socket.send(packet);
if (data.equals("bye")){
break;
}
}
socket.close();
}
}
结论:可以实现持续发送和持续接收
在线咨询:两人同时持续发送,持续接收
public class TalkSend implements Runnable{
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;
private String toIp;
private int toPort;
public TalkSend(int fromPort, String toIp, int toPort) {
this.fromPort = fromPort;
this.toIp = toIp;
this.toPort = toPort;
try {
socket = new DatagramSocket(fromPort);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
try {
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIp,this.toPort));
socket.send(packet);
if (data.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
public class TalkReceive implements Runnable{
DatagramSocket socket = null;
private int port;
private String msgFrom;
public TalkReceive(int port,String msgFrom) {
this.port = port;
this.msgFrom = msgFrom;
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
// 准备接收包裹
while (true){
try {
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(msgFrom+":"+receiveData);
if (receiveData.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
public class TalkStudent {
public static void main(String[] args) {
// 开启两个线程
new Thread(new TalkSend(7777,"127.0.0.1",9999)).start();
new Thread(new TalkReceive(8888,"老师")).start();
}
}
public class TalkTeacher {
public static void main(String[] args) {
// 开启两个线程
new Thread(new TalkSend(5555,"127.0.0.1",8888)).start();
new Thread(new TalkReceive(9999,"学生")).start();
}
}
统一资源定位符:定位互联网上的某一个资源
协议://ip地址:端口/项目名/资源 # http://127.0.0.1:8080/MrXie/Security.txt
public class UrlTest {
// http://127.0.0.1:8080/MrXie/Security.txt
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://127.0.0.1:8080/MrXie/Security.txt");
System.out.println(url.getProtocol()); // 协议
System.out.println(url.getHost()); // 主机
System.out.println(url.getPort()); // 端口
System.out.println(url.getPath()); // 文件
System.out.println(url.getFile()); // 文件全路径
System.out.println(url.getQuery()); // 参数
}
}
结果
http
127.0.0.1
8080
/MrXie/Security.txt
/MrXie/Security.txt
null
从网络上下载资源
public class UrlDown {
public static void main(String[] args) throws IOException {
// 1.下载地址
URL url = new URL("http://127.0.0.1:8080/MrXie/Security.txt");
// 2.连接到这个资源 HTTP
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("SecurityFile.txt");
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer))!= -1){
fos.write(buffer,0,len);
}
fos.close();
inputStream.close();
urlConnection.disconnect(); // 断开连接
}
}