网络编程
- 计算机网络:将地理位置不同的具有独立功能的多台计算计算及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
- 网络编程的目的:数据交换,通信
- 需要解决的问题:
- 如何准确定位网络上的一台主机和这台主机的某个资源(ip + 端口号)
- 找到主机后,如何传输数据?(网络通信协议(主要TCP,UDP))
1.1网络通信要素
-
IP类:InetAddress
- 本机ip(localhost):127.0.0.1
- ip地址分类:IPV4,4个字节组成。IPV6:128位。8个无符号整数;
- 公网(互联网)/私网(局域网)
-
域命:记忆IP问题
import java.net.InetAddress;
import java.net.UnknownHostException;
public class TestInetAddress {
public static void main(String[] args) {
//new InetAddress(); //无法new
try {
//查询本机IP地址
InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
System.out.println(inetAddress1);
InetAddress inetAddress2 = InetAddress.getByName("localhost");
System.out.println(inetAddress2);
InetAddress inetAddress3 = InetAddress.getLocalHost();
System.out.println(inetAddress3);
//常用方法测试
System.out.println(inetAddress1.getAddress());
System.out.println(inetAddress1.getCanonicalHostName());
System.out.println(inetAddress1.getHostAddress());
System.out.println(inetAddress1.getHostName());
//查询网站IP地址
InetAddress inetAddress11 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress11);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
-
端口:计算机程序进程相关;单协议下不同进程有不同的端口号(区分不同程序);
-
TCP,UDP各有端口号:0-65535;
-
端口分类:
- 公有端口(0-1023):HTTP:80 ; HTTPS: 443; FTP:21 ; Telent:23
- 程序注册端口:1024-49151,分配给用户或程序
- 动态、私有:49152-65535
-
import java.net.InetSocketAddress;
public class TestInetSocketAddress {
public static void main(String[] args) {
//查看端口号
InetSocketAddress inetSocketAddress1 = new InetSocketAddress("127.0.0.1",8080);
System.out.println(inetSocketAddress1);
InetSocketAddress inetSocketAddress2 = new InetSocketAddress("localhost",8080);
System.out.println(inetSocketAddress2);
//常用方法
System.out.println(inetSocketAddress1.getAddress());
System.out.println(inetSocketAddress1.getHostName());//地址
System.out.println(inetSocketAddress1.getHostString());
System.out.println(inetSocketAddress1.getPort());//端口
}
}
-
网络通信协议:速率,传输码率,代码结构,传输控制…
-
太过复杂:分层—>TCP/IP协议簇
-
TCP:用户传输协议(类似打电话)
- 连接,稳定
- 三次握手,四次挥手
最少需要三次,保证稳定连接 A:你瞅啥? B:瞅你咋地? A:干一场 挥手: A:我要走了 B:你真的要走了吗? B:你真的真的要走了吗? A:我真的要走了!
- 客户端,服务端
- 传输完成,释放连接,效率低
-
UDP:用户数据包协议(类似发短信)
- 不连接,不稳定
- 客户端,服务段没有明确的界限
- 不管有没有准备好,都可以发给你
- DDoS攻击,饱和攻击
TCP/IP
客户端
- 连接服务器 Socket
- 发送消息
服务器
1.建立服务端口 ServerSocket
2.等待用户的连接 accept
3.接收用户的消息
//服务器端 public class TcpServerDemo1 { public static void main(String[] args) { ServerSocket serverSocket = null;//方便统一关闭资源 Socket socket = null; InputStream is = null; ByteArrayOutputStream baos = null; try { //1.服务器得有一个地址 serverSocket = new ServerSocket(9999); //2. 等待客户端连接过来 socket = serverSocket.accept();//服务器方法accept()监听 //3. 读取客户端的消息 is = socket.getInputStream(); /* * 一般读方法,不能超过1024,会出现乱码 * byte[] buffer = new byte[1024]; * int len; * while ((len = is.read(buffer)) != -1) { * String msg = new String(buffer,0,le); * System.out.println(msg); * } * */ //使用管道流 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 TcpClientDemo1 { public static void main(String[] args) { Socket socket = null; OutputStream os = null; try { //1.要知道服务器的地址和端口号 InetAddress inetAddress = InetAddress.getByName("127.0.0.1"); int port = 9999; //2.创建一个 socket 连接 socket = new Socket(inetAddress,port); //3. 发送消息 IO 流 os = socket.getOutputStream(); os.write("你好,欢迎学习Java".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(); } } } } }
TCP传输文件
public class TcpClientDemo2 { public static void main(String[] args) throws Exception { //1.创建一个Socket连接 Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000); //2.创建一个输出流 OutputStream os = socket.getOutputStream(); //3.文件流,读取文件 FileInputStream fis = new FileInputStream(new File("ludashi.jpg")); //4.写出文件 byte[] buffer = new byte[1024]; int len; while((len=fis.read(buffer)) != -1) { os.write(buffer,0,len); } //通知服务器,已经传输完毕 socket.shutdownOutput(); //确定服务器接收完毕,才能断开连接 InputStream inputStream = socket.getInputStream(); //String byte[] ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer2 = new byte[1024]; int len2; while((len2=inputStream.read(buffer2)) != -1) { baos.write(buffer2,0,len2); } System.out.println(baos.toString()); //5.关闭资源 baos.close(); inputStream.close(); fis.close(); os.close(); socket.close(); } }
public class TcpServerDemo2 { public static void main(String[] args) throws IOException { //1.创建服务端口 ServerSocket serverSocket = new ServerSocket(9000); //2.监听客户端的连接 Socket socket = serverSocket.accept();//阻塞式监听,会一直等待 //3.获取输入流 InputStream is = socket.getInputStream(); //4.文件输出 FileOutputStream fos = new FileOutputStream(new File("receive.jpg")); byte[] buffer = new byte[1024]; int len; while((len=is.read(buffer))!=-1) { fos.write(buffer,0,len); } //通知客户端接收完毕 OutputStream os = socket.getOutputStream(); os.write("我已接收完毕,你可以断开连接".getBytes()); //关闭资源 fos.close(); is.close(); socket.close(); serverSocket.close(); } }
Tomcat
服务端
- 自定义服务S
- Tomcat服务器S:(java后台开发)
客户端
- 自定义 C
- 浏览器 B
UDP
类似发短信,不用建立连接,只要知道地址即可
示例:UDP发送消息
//UDP没有客户端,服务器,起名只是便于区分 public class UdpServerDemo1 { public static void main(String[] args) throws Exception { //开放端口 DatagramSocket socket = new DatagramSocket(9000); //接收数据包 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(); } }
//UDP,不需要连接服务器 public class UdpClientDemo1 { public static void main(String[] args) throws Exception { //1.建立一个Socket DatagramSocket socket = new DatagramSocket(); //2.建立一个包 String msg = "hello,Server!"; //发送给谁 InetAddress address = InetAddress.getByName("localhost"); int port = 9000; //DatagramPacket(数据,数据的长度起始,发送给谁) DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,address,port); //3.发送包 socket.send(packet); //4.关闭流 socket.close(); } }
UDP咨询
示例:循环发送和接收
public class UdpReceiverDemo01 { 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);//阻塞式接收包裹 //断开连接 bye 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 UdpSenderDemo01 { public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(8888); //准备数据:从控制台读取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(); } }
示例:UDP多线程在线咨询
-
public class TalkSend implements Runnable{
DatagramSocket socket = null;
BufferedReader reader = null;
private String toIP;
private int toPort;
private int fromPort;
public TalkSend(String toIP, int toPort, int fromPort) {
this.toIP = toIP;
this.toPort = toPort;
this.fromPort = fromPort;
try {
socket = new DatagramSocket(fromPort);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
public TalkSend() {
}
@Override
public void run() {
while (true) {
String data = null;
try {
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 (Exception e) {
e.printStackTrace();
}
}
socket.close();
}
}
public class TalkReceive implements Runnable{
private int port;
DatagramSocket socket = null;
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);//阻塞式接收包裹
//断开连接 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 e) {
e.printStackTrace();
}
}
socket.close();
}
}
public class TalkStudent {
public static void main(String[] args) {
new Thread(new TalkSend("localhost",9999,7777)).start();
new Thread(new TalkReceive(8888,"teacher")).start();
}
}
public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TalkSend("localhost",8888,5555)).start();
new Thread(new TalkReceive(9999,"student")).start();
}
}
URL
URL:统一资源定位符,定位互联网上的某一个资源
1 协议: //ip地址:端口/项目名/资源
URL下载网络资源示例:下载网易云上的一副图片
import java.net.MalformedURLException;
import java.net.URL;
//URL类示意
public class URLDemo {
public static void main(String[] args) {
URL url = null;
try {
url = new URL("http://localhost:8080/helloworld/index.jsp?username=jay&password=123");
} catch (MalformedURLException e) {
e.printStackTrace();
}
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());//参数
}
}
//URL下载网络资源
public class UrlDown {
public static void main(String[] args) throws IOException {
//1.下载地址
URL url = new URL("https://p4.music.126.net/Nl4mFBPeN4Lqtqn3KOAvXQ==/109951166171044898.jpg?param=200y200");
//2.连接到这个资源 HTTP
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("test.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len=inputStream.read(buffer)) != -1) {
fos.write(buffer,0,len);
}
//关闭资源
fos.close();
inputStream.close();
urlConnection.disconnect();
}
}