网络编程
网络编程
计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
计算机网络主要是由一些通用的、可编程的硬件互连而成的,而这些硬件并非专门用来实现某一特定目的(例如,传送数据或视频信号)。这些可编程的硬件能够用来传送多种不同类型的数据,并能支持广泛的和日益增长的应用。
网络编程作用
1、通过网络编程,我们可以实现通过网络编程的程序访问其他的计算机实现资源共享和数据通信
2、我们要做的是实现两台计算机之间的通信:
需要先通过电脑的ip地址找到计算机,
然后通过应用程序的端口号找到需要通信的应用程序
然后按照某种协议发送数据
ip:准确找到网络上的一台主机,
端口,定位到这个主机上的某个资源
javaweb:网页编程,B/S
网络编程:TCP/IP c/s
实现网络通信,通信双方地址:ip,端口号,
网络通信协议
网络编程的两个主要问题
如何准确定位到网络上一台或者多台主机。ip + 端口号
找到主机之后如何通信。网络通信协议,udp , tcp
ip
inetAddress类,IP地址
localhost本机,127.0.0.1
ip地址分类:
公网(互联网),私网(局域网)
ipv4,ipv6
域名,解决记忆ip地址问题
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Demo1 {
public static void main(String[] args) {
try {
//获得网站ip地址
InetAddress byName1 = InetAddress.getByName("www.baidu.com");
System.out.println(byName1);
//获得本机地址
InetAddress byName2 = InetAddress.getByName("127.0.0.1");
System.out.println(byName2);
InetAddress byName3 = InetAddress.getByName("localhost");
System.out.println(byName3);
InetAddress byName4 = InetAddress.getLocalHost();
System.out.println(byName4);
//常用方法
byte[] address = byName1.getAddress();
for (byte a : address) {
System.out.println(a);
}
System.out.println(byName1.getCanonicalHostName());//获得规范的ip名
System.out.println(byName1.getHostAddress());//获得ip地址
System.out.println(byName1.getHostName());//获得域名
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
TCP/ip
TCP:打电话,需要确认连接安全
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议
端口:表示计算机中程序的一个进程;
不同的进程有不同的端口号,端口号不能冲突,用来区分软件。
被规定再0-65535之间。
有TCP,UDP端口分类,故有65535 * 2个端口。单个协议下端口号不能冲突
端口分类:
共有端口,0-1023,http:80,https:443,FTP:21,Telent:23
程序注册端口,1024-49151,分配用户或者程序
netstat -ano ,查看所有端口
netstat -ano |findstr "(端口号)",查看指定的端口
tasklist|findstr "(端口号)" , 查看特定进程端口
import java.net.InetSocketAddress;
public class Demo2 {
public static void main(String[] args) {
InetSocketAddress inetSocketAddress = new InetSocketAddress("localhost",8080);
//InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1",8080);
System.out.println(inetSocketAddress);//就是toString方法
System.out.println(inetSocketAddress.getAddress());//主机地址
System.out.println(inetSocketAddress.getHostName());//主机名
System.out.println(inetSocketAddress.getPort());//端口号
}
}
通信协议
服务端
- 建立服务的端口ServerSocket
- 等待接收用户发送的消息accept
- 接收用户的消息
客户端
- 获取服务端的地址
- 创建Socket连接
- 发送消息
package TcoIpTest;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class TcpClientDemo {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream = null;
//要知道服务器的地址
try {
InetAddress name = InetAddress.getByName("localhost");
//获得端口号
int port = 3655;
//创建socket连接
socket = new Socket(name,port);
//发送消息
outputStream = socket.getOutputStream();
outputStream.write("hello world!".getBytes());
} catch (Exception e) {
e.printStackTrace();
}finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package TcoIpTest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServiceDemo {
public static void main(String[] args) {
ServerSocket socket = null;
Socket accept = null;
InputStream inputStream = null;
ByteArrayOutputStream stream = null;
//创建服务器端口号
try {
socket = new ServerSocket(3655);
accept = socket.accept();//使该端口一直监听等待用户发送信息
inputStream = accept.getInputStream();
/*byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) != -1){
String str = new String(buffer,0,len);
System.out.println(str);
}//可能会有问题,中文的话可能会乱码
inputStream.close();*/
byte[] bytes = new byte[1024];
stream = new ByteArrayOutputStream();
int len;
while ((len = inputStream.read(bytes)) != -1){
stream.write(bytes,0,len);
}
System.out.println(stream.toString());
} catch (IOException e) {
e.printStackTrace();
}finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (accept != null) {
try {
accept.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
文件上传
package TcoIpTest;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
//文件上传功能
public class FileClient {
public static void main(String[] args) throws Exception {
//获取服务端地址
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
OutputStream outputStream = socket.getOutputStream();
//发送消息
//读文件
FileInputStream fileInputStream = new FileInputStream("LP.png");
byte[] bytes = new byte[1024];
int len;
//发送文件
while((len = fileInputStream.read(bytes)) != -1){
outputStream.write(bytes);
}
//通知服务器我已经传输完了
socket.shutdownOutput();
InputStream inputStream = socket.getInputStream();
//确认服务端接收完毕才能断开连接
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] bytes1 = new byte[1024];
int len1;
while ((len1 = inputStream.read(bytes1)) != -1){
byteArrayOutputStream.write(bytes1,0,len1);
}
System.out.println(byteArrayOutputStream.toString());
//关闭流
byteArrayOutputStream.close();
inputStream.close();
fileInputStream.close();
outputStream.close();
socket.close();
}
}
package TcoIpTest;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class FileServer {
public static void main(String[] args) throws Exception {
//获取ServerSocket
ServerSocket serverSocket = new ServerSocket(9000);
Socket accept = serverSocket.accept();//获取accept等待端口消息
InputStream inputStream = accept.getInputStream();
//管道流
FileOutputStream fileOutputStream = new FileOutputStream("zyf.png");
byte[] bytes = new byte[1024];
int len;
//接收文件
while ((len = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes);
}
//通知客户端我接收完了
OutputStream outputStream = accept.getOutputStream();
outputStream.write("goodbye!".getBytes());
//关闭流
outputStream.close();
fileOutputStream.close();
inputStream.close();
accept.close();
serverSocket.close();
}
}
TCP三次握手
客户端向服务端发出消息,并进入等待状态,服务器搜到消息,并向客户端发送反馈消息,,并进入等待状态,然后客户端接收服务端反馈消息,并向服务端发送一个OK确认消息,进入安全连接状态,服务端接受到这个确认消息后也进入安全连接状态
TCP四次挥手
客户端发送结束消息,再见,服务端接收此消息,并作出响应,收到,客户端接收此消息,进入等待连接终止状态。然后,服务端再发送一个消息,问你真的要走了吗?客户端接收到这个消息,反馈一个真的走了的消息,然后客户端连接终止,服务端接受这个消息,也进入连接终止状态。
udp
发短信,不需要确认连接
Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。
区别
UDP和TCP协议的主要区别是两者在如何实现信息的可靠传递方面不同。TCP协议中包含了专门的传递保证机制,当数据接收方收到发送方传来的信息时,会自动向发送方发出确认消息;发送方只有在接收到该确认消息之后才继续传送其它信息,否则将一直等待直到收到确认信息为止。与TCP不同,UDP协议并不提供数据传送的保证机制。如果在从发送方到接收方的传递过程中出现数据包的丢失,协议本身并不能做出任何检测或提示。因此,通常人们把UDP协议称为不可靠的传输协议。
TCP 是面向连接的传输控制协议,而UDP 提供了无连接的数据报服务;TCP 具有高可靠性,确保传输数据的正确性,不出现丢失或乱序;UDP 在传输数据前不建立连接,不对数据报进行检查与修改,无须等待对方的应答,所以会出现分组丢失、重复、乱序,应用程序需要负责传输可靠性方面的所有工作;UDP 具有较好的实时性,工作效率较 TCP 协议高;UDP 段结构比 TCP 的段结构简单,因此网络开销也小。TCP 协议可以保证接收端毫无差错地接收到发送端发出的字节流,为应用程序提供可靠的通信服务。对可靠性要求高的通信系统往往使用 TCP 传输数据。
package TcoIpTest;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class DemoUDP {
public static void main(String[] args) throws Exception {
//创建Socket
DatagramSocket datagramSocket = new DatagramSocket();
//建数据包
String msg = "hello world!";
//发给谁
InetAddress localhosts = InetAddress.getByName("localhost");
int port = 4444;
//参数:数据,起始位置,终止位置,ip地址,端口
DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhosts,port);
//发送包
datagramSocket.send(datagramPacket);
datagramSocket.close();//关闭流
}
}
package TcoIpTest;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class Demoerver {
public static void main(String[] args) throws Exception {
//开放端口
DatagramSocket datagramSocket = new DatagramSocket(4444);
//接收数据包
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length);
datagramSocket.receive(datagramPacket);
byte[] data = datagramPacket.getData();
System.out.println(new String(data));
datagramSocket.close();
}
}
多线程实现聊天
package TcoIpTest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class TalkSend implements Runnable{
private DatagramSocket datagramSocket = null;
private BufferedReader bufferedReader = null;
private DatagramPacket datagramPacket = null;
private int ToPort;
private int fromPort;
private String Address;
public TalkSend(int toPort, int fromPort, String address) {
this.ToPort = toPort;
this.fromPort = fromPort;
this.Address = address;//IP
try {
this.datagramSocket = new DatagramSocket(this.fromPort);
bufferedReader = new BufferedReader(new InputStreamReader(System.in));
}catch (Exception e){
e.printStackTrace();
}
}
public void run() {
while (true){
try {
byte[] bytes = bufferedReader.readLine().getBytes();
datagramPacket = new DatagramPacket(bytes,0,bytes.length,InetAddress.getByName(Address),ToPort);
datagramSocket.send(datagramPacket);
if (new String(bytes).equals("bye"))
break;
}catch (Exception e){
e.printStackTrace();
}
}
datagramSocket.close();
}
}
package TcoIpTest;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class TalkReceive implements Runnable {
DatagramSocket datagramSocket = null;
private int fromPort;
private String name;
public TalkReceive(int fromPort,String name) {
this.fromPort = fromPort;
this.name = name;
try {
this.datagramSocket = new DatagramSocket(this.fromPort);
}catch (Exception e){
e.printStackTrace();
}
}
public void run() {
while (true){
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length);
try {
datagramSocket.receive(datagramPacket);
byte[] data = datagramPacket.getData();
String s = new String(data,0,data.length);
System.out.println(name + " : " + s);
if (s.equals("bye")) break;
}catch (Exception e){
e.printStackTrace();
}
}
datagramSocket.close();
}
}
package demoTest;
import TcoIpTest.TalkReceive;
import TcoIpTest.TalkSend;
public class StudentChat {
public static void main(String[] args) {
new Thread(new TalkSend(5555,8989,"localhost")).start();
new Thread(new TalkReceive(7777,"老师")).start();
}
}
package demoTest;
import TcoIpTest.TalkReceive;
import TcoIpTest.TalkSend;
public class TeacherChat {
public static void main(String[] args) {
new Thread(new TalkSend(7777,8888,"localhost")).start();
new Thread(new TalkReceive(5555,"张三")).start();
}
}
URL
统一资源定位系统(uniform resource locator;URL)是因特网的万维网服务程序上用于指定信息位置的表示方法。它最初是由蒂姆·伯纳斯·李发明用来作为万维网的地址。现在它已经被万维网联盟编制为互联网标准RFC1738。
协议://ip地址:端口/项目名/资源
只能多不能少
package demoTest;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
//网络下载
public class URLDemo {
public static void main(String[] args) throws Exception {
URL url = new URL("https://m10.music.126.net/20230110164640/153fd3eaa8714a8ae04a9e89cc4310f3/yyaac/obj/wonDkMOGw6XDiTHCmMOi/14056213079/2d6e/0cd1/98d3/c5b072fe9d2ee05f8d3cc5385147f4bc.m4a");
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
byte[] bytes = new byte[1024];
int len;
FileOutputStream fileOutputStream = new FileOutputStream("aaa.m4a");
while ((len = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes);
}
fileOutputStream.close();
inputStream.close();
//URL url = new URL("https://www.kuangstudy.com/course?cid=1");
// System.out.println(url.getProtocol());//协议
// System.out.println(url.getPort());//端口
// System.out.println(url.getHost());//主机ip
// System.out.println(url.getFile());//资源文件
// System.out.println(url.getPath());//资源路径
// System.out.println(url.getQuery());//提交参数
// System.out.println(url.getAuthority());//主机ip
// System.out.println(url.getContent());//获得上下文
// System.out.println(url.getUserInfo());//用户信息
}
}