java网络编程
1.1 概述
1.2 网络通信的要素
如何实现网络通信?
通信双方地址:
- 地址ip
- 端口号
- 127.0.0.1:8080
OSI七层模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w2Vt3rrJ-1641116549495)(C:\Users\yanyu\AppData\Roaming\Typora\typora-user-images\image-20211225142933939.png)]
小结:
- 网络编程中有两个主要问题
- 如何准确定位到网络上的一台或者多台主机
- 找到主机之后如何通信
- 网络编程中的要素
- IP和端口号 IP
- 网咯通信协议 UDP、TCP
- IP和端口号 IP
- 万物皆对象
1.3 IP地址
ip地址:InetAdddress
- 唯一定义网络上的一台或者多台地址
- ping 127.0.0.1:本机 localhost
- ip地址的分类
- IPV4\IPV6
- IPV4,127.0.0.1,四个字节,32位,0-255,42亿
- IPV6,128位
- 公网–私网
- ABCD类地址
- 192.168.xx.xx
- IPV4\IPV6
- 域名:记忆IP问题
- IP:纯数字
- URL:统一资源定界符,DNS服务器
//获取ip,InetAddress类
public static void main(String[] args) {
InetAddress ip=null;
try {
ip = InetAddress.getByName("127.0.0.1");
System.out.println(ip);
ip = InetAddress.getByName("www.baidu.com");
System.out.println(ip);
System.out.println(InetAddress.getLocalHost());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
1.4 端口
端口计算机上的表示一个进程
-
不同进程具有不同端口,用来区分软件
-
一个int大小,0-65535
-
TCP,UDP, 单个协议下,同一端口并不冲突
-
公共端口 0 - 1024
-
http:80
-
https:443
-
ftp:21
-
Telent:23
-
-
程序注册端口:1024-49151,用户程序公用
-
Tomcat:8080
-
MySql:3306
-
Oracle:1521
-
-
动态、私有:49152-65535
netstat -ano #查看所有端口 netstat -ano| findstr “5900” #查看指定端口 takelist | findstr "8696" #查看相应端口
-
socketAddress类,将地址和端口结合
InetAddress ip=null;
try {
ip = InetAddress.getByName("127.0.0.1");
InetSocketAddress socketAddress = new InetSocketAddress(ip, 80);
InetSocketAddress socketAddress1 = new InetSocketAddress("127.0.0.1", 80);
System.out.println(socketAddress);
System.out.println(socketAddress1);
socketAddress.getAddress();
socketAddress.getPort();
} catch (UnknownHostException e) {
e.printStackTrace();
}
1.5 通信协议
procedure、protocol
通信协议:通信规则,波特率,信道,…
TCP协议:传输控制协议,Transmission Control Protocol
UDP协议:用户数据报协议,User Data Protocol
TCP:可靠全双工通信,建立连接后通信
三次握手
A:你好
B:你好
A:我们开始聊天!
四次挥手
A:我要断开连接了
B:你真的断开连接了吗
B:你确定你断开连接
A:是的
UDP:不可靠半双工通信,不建立连接,直接向ip:端口发送消息
1.6 TCP实现聊天
java socket在创建构造函数的时候是创建的连接对象的地址,如果不使用有参构造,那么需要手动connect(),一般网络连接流程如下:
![img](https://img-blog.csdnimg.cn/img_convert/41eb6e3df828bedae464a1f430ce4aba.png)
package com.zp;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class TcpService {
static OutputStream os =null;
static InputStream is=null;
static Socket socket = null;
static ServerSocket serverSocket = null;
public static void main(String[] args) {
Scanner cin = new Scanner (System.in);
try {
System.out.println("服务器启动");
//构造ServerSocket实例,指定端口监听客户端的连接请求
serverSocket = new ServerSocket(8080);
// 建立跟客户端的连接
socket = serverSocket.accept();
// 向客户端发送消息
is = socket.getInputStream();
os = socket.getOutputStream();
InputStreamReader isr=new InputStreamReader(is,"utf-8");
OutputStreamWriter osw = new OutputStreamWriter(os,"utf-8");
//osw.write(msg);
// 接受客户端的响应
new Thread() {
public void run() {
// TODO Auto-generated method stub
while (true) {
//byte b[] = new byte[1024];
char[] cha=new char[1024];
int len=0;
try {
len = isr.read(cha);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("小明说:"+new String(cha,0,len));
}
}
}.start();
//向客户端发送消息
new Thread(){
public void run(){
// TODO Auto-generated method stub
while(cin.hasNext()){
String str=cin.next();
try {
//osw.write(str);
os.write(str.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
package com.zp;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
public class TcpClient {
static Socket socket = null;
static InputStream is = null;
static OutputStream os = null;
public static void main(String[] args) {
Scanner cin = new Scanner (System.in);
try {
// 对服务端发起连接请求
System.out.println("已经连接服务器");
socket = new Socket("localhost", 8080);
is = socket.getInputStream();
os = socket.getOutputStream();
InputStreamReader isr=new InputStreamReader(is,"utf-8");
OutputStreamWriter osw = new OutputStreamWriter(os,"utf-8");
os.write("已经接服务器。".getBytes());
//接收服务器信息
new Thread() {
public void run() {
// TODO Auto-generated method stub
while (true) {
//byte b[] = new byte[1024];
char[] cha=new char[1024];
int len=0;
try {
len = isr.read(cha);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("小红说:"+new String(cha,0,len));
}
}
}.start();
// 给服务端发送响应信息
new Thread(){
public void run(){
// TODO Auto-generated method stub
while(cin.hasNext()){
String str=cin.next();
try {
//osw.write(str);
os.write(str.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
注意:
- socket IO流读不到会自动阻塞,除非遇到了EOF或者IOException
- 正是因此,我觉得,TCP实现全双工通信就分成两个线程
1.7 UDP
UDP一般工作流程:
package com.zp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class UDPSender implements Runnable{
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;
private String toIP;
private int toPort;
public UDPSender(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 (Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
try {
String data = reader.readLine();
byte[] datas = data.getBytes();
System.out.println(datas.length);
DatagramPacket packet = new DatagramPacket(datas, 0, datas.length,
new InetSocketAddress(this.toIP, this.toPort));
socket.send(packet);
if (data.equals("bye")){
break;
}
} catch (IOException exception) {
exception.printStackTrace();
}
}
socket.close();
}
}
package com.zp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPReceiver implements Runnable{
DatagramSocket socket = null;
private int port;
private String msgFrom;
public UDPReceiver(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);
//断开连接 bye
byte[] data = packet.getData();
String receiveData = new String(data, 0, data.length);
System.out.println(msgFrom + ":" + receiveData);
if (receiveData.equals("bye")){
break;
}
} catch (IOException exception) {
exception.printStackTrace();
}
}
socket.close();
}
}
注意:
- UDP是只管发送的IP,接受他是没有IP的,因为他是不事先建立连接的通信
1.8 URL
https://www.baidu.com/
统一资源定位符:定位资源的,定位互联网上的某一个资源
DNS 域名解析 www.baidu.com/ xxx.xxx.xxx
- 协议://ip地址:端口/项目名/资源
public class URLDemo01 {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://localhost:8080/helloworld/index.jsp?username=kuangshen&password=123");
System.out.println(url.getProtocol()); //协议
System.out.println(url.getHost()); //主机ip
System.out.println(url.getPort()); //端口
System.out.println(url.getPath()); //文件地址
System.out.println(url.getFile()); //文件全路径
System.out.println(url.getQuery()); //参数
}
}
- 网络资源下载
public class UrlDown {
public static void main(String[] args) throws Exception {
//1.下载地址
URL url = new URL("");
//2.连接到这个资源 HTTP
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("tu.jpg");
byte[] buffer = new byte[1024];
int len;
while((len=inputStream.read(buffer)) != -1){
fos.write(buffer, 0, len);//写出这个数据
}
fos.close();
inputStream.close();
urlConnection.connect();
}
}