什么是网络编程?
网络通信的要素:
通信双方的地址:
1、ip , 端口号
2、网络通信协议 TCP,UDP
IP:
唯一确定网络上的一台计算机
本机:127.0.0.1 或 loalhost
端口号:
所谓的端口,就好像是门牌号一样,客户端可以通过ip地址找到对应的服务器端,但是服务器端是有很多端口的,每个应用程序对应一个端口号,通过类似门牌号的端口号,客户端才能真正的访问到该服务器。为了对端口进行区分,将每个端口进行了编号,这就是端口号。
一个IP地址的端口通过16bit进行编号,最多可以有65536个端口。
其中,0~1023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。
获取IP:InetAddress
package com.smiledog.wangluobiancheng.socket;
/*
@ClassName UDPDemo
@Author SmILeDog
@Date 2021/5/11
@Time 13:39
*/
import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
// CSDN:InetAddress类没有构造方法,所以不能直接new出一个对象;
// 可以通过InetAddress类的静态方法获得InetAddress的对象;
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);//DESKTOP-IDATELU/172.16.16.107 主机名/ip地址
InetAddress address = InetAddress.getLocalHost();
System.out.println("计算机名:" + address.getHostName());
System.out.println("IP地址:" + address.getHostAddress());
}
}
运行结果:
DESKTOP-IDATELU/172.16.16.107
计算机名:DESKTOP-IDATELU
IP地址:172.16.16.107
TCP和UDP:
TCP:用户传输协议 (三次握手,四次挥手)
比如:打电话 ===》需要建立连接
需要连接,较稳定
客户端,服务端
传输完成,释放连接,效率低
- 第一次握手,客户端向服务器端发出连接请求,等待服务器确认。
- 第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。
- 第三次握手,客户端再次向服务器端发送确认信息,确认连接。
三次握手:
客户端:你好服务器,我要和你建立连接
服务器:好的客户端,已经答应和你建立连接并通知了服务器应用程序(单向连接建立)
客户端:好的服务器,已经通知应用程序进行连接(双向连接建立)
四次挥手:
客户端:你好服务器,我要和你断开连接
服务器:好的客户端,已经通知服务器应用程序
服务器:服务器应用程序通知我可以断开连接了(服务器断开连接)
客户端:好的服务器,已经通知应用程序断开了(客户端断开连接)
UDP:用户数据报协议
比如:发短信 ===》不需要建立连接
不需要连接,不稳定
客户端,服务端 两者没有明确的界限
不管你准没准备好接收,反正我是发给你了
TCP案例:文件的上传
package com.smiledog.wangluobiancheng.socket.TCPDemo.test2;
/*
@ClassName Client
@Author SmILeDog
@Date 2021/5/11
@Time 17:02
模拟客户端 进行 上传文件
*/
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
//创建客户端 指定目标ip和端口
Socket socket = new Socket(InetAddress.getLocalHost(),12345);
//通过socket获取输出流
OutputStream os = socket.getOutputStream();
//读取文件,传给服务器
FileInputStream fis = new FileInputStream(new File("day15\\1.jpg")); //读取指定文件
byte[] bys = new byte[1024];
int line;
while ((line = fis.read(bys)) != -1){
os.write(bys,0,line);
}
socket.shutdownOutput(); //调用停止输出流,用于停止阻塞,让程序走完
InputStream is = socket.getInputStream(); //获取输入流,读取服务器返回信息!
int read = is.read(bys);
System.out.println(new String(bys,0,read));
//关闭资源
os.close();
fis.close();
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package com.smiledog.wangluobiancheng.socket.TCPDemo.test2;
/*
@ClassName Server
@Author SmILeDog
@Date 2021/5/11
@Time 17:02
模拟服务器 进行 接收文件
ps: 添加多线程,用于多个用户上传文件的需求
ps:应该添加一个判断,获取文件类型,然后确定传进来的是什么文件,把jpg变成可变的。
*/
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
public class Server {
public static void main(String[] args) throws IOException {
//创建服务器 指定IP
ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("服务器已打开,等待上传。。。");
while (true) {
Socket socket = serverSocket.accept(); //创建服务器监听
new Thread(new ServerThread(socket)).start(); //传入客户端 开启线程
}
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package com.smiledog.wangluobiancheng.socket.TCPDemo.test2;
/*
@ClassName ServerThread
@Author SmILeDog
@Date 2021/5/11
@Time 17:56
*/
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
public class ServerThread implements Runnable{
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();//通过客户端获取输入流
//创建个字符串用于接收的文件命名问题,避免名称重复问题 客户端的主机名+当前时间+8位的随机整数
String fileName = socket.getInetAddress().getHostName() + System.currentTimeMillis() + new Random().nextInt(99999999);
//创建文件输出流,进行写数据
FileOutputStream fos = new FileOutputStream(new File("day15\\" + fileName + ".jpg")); //创建字节输出流
//读取数据内容
byte[] bys = new byte[1024];
int line;
while ((line = is.read(bys)) != -1) { //读取客户端传入的数据
fos.write(bys, 0, line); //读取的数据写入服务器
}
OutputStream os = socket.getOutputStream(); //获取输出流,写入返回客户端信息!
os.write("上传成功!".getBytes());
System.out.println("来自:"+socket.getInetAddress().getHostAddress()+"上传文件成功!");
//关闭资源
fos.close();
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UDP案例:公共聊天室
package com.smiledog.wangluobiancheng.socket.UDPDemo.chijiuhua;
/*
@ClassName SendDemo
@Author SmILeDog
@Date 2021/5/11
@Time 14:48
模拟客户端
*/
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class SendDemo {
public static void main(String[] args) throws IOException {
//创建客户端
DatagramSocket socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while (true){ //一直输出数据 直到输入bye,不区分大小写
System.out.println("请输入:");
String s = sc.nextLine();
if (s.equalsIgnoreCase("bye")){
socket.close(); //客户端输入bye,关闭资源
}
byte[] bys = s.getBytes(); //将字符串转成数组
//将数据打包 : DatagramPacket(数组,长度,目标ip地址,目标端口)
DatagramPacket packet = new DatagramPacket(bys, bys.length,InetAddress.getLocalHost() , 12306);
socket.send(packet); //发送包
//socket.close(); //关闭资源
}
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package com.smiledog.wangluobiancheng.socket.UDPDemo.chijiuhua;
/*
@ClassName ReceiveDemo
@Author SmILeDog
@Date 2021/5/11
@Time 15:43
模拟服务器
*/
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//定义一个接收端,并指定端口号
DatagramSocket socket = new DatagramSocket(12306);
while (true) {
//接受客户端传过来的数据包
byte[] bys = new byte[1024]; //定义数组接收数据包
// 解析数据包 ,客户端传过来的数据都在这个packet里边了
DatagramPacket packet = new DatagramPacket(bys, bys.length);
socket.receive(packet); //接收数据包内容
String ip = packet.getAddress().getHostAddress(); //获取前端传过来的包中的ip地址
bys = packet.getData(); //获取包中的数据内容
int datalength = packet.getLength(); //获取文件内容的大小,如果直接打印bys的大小,打印的是初始化那个大小的值
System.out.println("packet.getData().length:"+datalength);
String data = new String(bys, 0, datalength);
System.out.println("来自:" + ip + "内容为:" + data);
}
}
}
URL:下载网络资源
package com.smiledog.wangluobiancheng;
/*
@ClassName URlDemo
@Author SmILeDog
@Date 2021/5/11
@Time 20:11
*/
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
public class URlDemo {
public static void main(String[] args) throws IOException {
//下载地址
URL url = new URL("https://m701.music.126.net/20210511205517/3f7bba4fb2bc0c1c9703573ea695fbf9/jdyyaac/525b/0f5d/060c/e1c731b12687d4fe07cc1fac64103777.m4a");//括号里是网络资源的网址
String file = url.getPath(); //获取文件路径
int i = file.lastIndexOf("."); //返回指定字符最后一次出现的位置
String sub = file.substring(i);
//连接到资源
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//调用字节输入流
InputStream is = urlConnection.getInputStream();
//创建文件输出流
//避免名称重复
SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss"); //格式化样式
String format = sdf.format(new Date()); //格式化
String fileName= format;
FileOutputStream fos = new FileOutputStream("E:\\music\\"+fileName+sub);
byte[] bys = new byte[1024];
int len;
while ((len = is.read(bys))!=-1){ //读取资源
fos.write(bys,0,len); //把资源写入本地
}
//关闭资源
fos.close();
is.close();
urlConnection.disconnect();
}
}
控制台公共聊天室:
package com.yunhe.socket;
/*
@ClassName Client
@Author SmILeDog
@Date 2021/6/8
@Time 16:33
模拟客户端
*/
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// String ip = "172.16.16.100";
String ip = "127.0.0.1";
int port = 12306;
String line = null;
Socket socket = null;
InputStream is = null;
OutputStream os = null;
BufferedReader br = null;
BufferedWriter bw = null;
try {
while (true){
//监听端口
socket = new Socket(ip,port);
//获取字节输入流
is = socket.getInputStream();
//获取字节输出流
os = socket.getOutputStream();
//获取字符缓冲输入流
br = new BufferedReader(new InputStreamReader(is));
//获取字符缓冲输出流
bw = new BufferedWriter(new OutputStreamWriter(os));
//客户端发送数据
System.out.println("请输入需要发送给服务器的内容:");
String str = sc.nextLine();
bw.write(str);//发送数据
bw.flush(); //刷新流
socket.shutdownOutput();
//接受服务器端的相应数据
while ((line = br.readLine()) !=null){
System.out.println("收到服务器端的响应内容:"+line); //打印相应内容
}
socket.shutdownInput();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bw!=null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (br!=null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os!=null){
try {
os.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();
}
}
}
}
}
package com.yunhe.socket;
/*
@ClassName server
@Author SmILeDog
@Date 2021/6/8
@Time 16:54
模拟服务器端
*/
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class server {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
int port = 12306;
String line = null;
String str = null;
Socket socket = null;
ServerSocket serverSocket = null;
InputStream is = null;
OutputStream os = null;
BufferedReader br = null;
BufferedWriter bw = null;
serverSocket = new ServerSocket(port);
try {
while (true) {
System.out.println("======服务器端正在接收数据======");
socket = serverSocket.accept();
//获取字节输入流
is = socket.getInputStream();
//获取字节输出流
os = socket.getOutputStream();
//获取字符缓冲输入流
br = new BufferedReader(new InputStreamReader(is));
//获取字符缓冲输出流
bw = new BufferedWriter(new OutputStreamWriter(os));
//接受服务器端的相应数据
while ((line = br.readLine()) != null) {
System.out.println("收到客户端"+socket.getInetAddress().getHostAddress()+"发来的消息:" + line); //打印相应内容
}
socket.shutdownInput();
//服务器端响应数据
System.out.println("请回复需要响应的内容:");
str = sc.nextLine();
bw.write(str);//发送数据
bw.flush(); //刷新流
socket.shutdownOutput();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bw!=null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (br!=null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}