什么是网络编程?
网络通信的要素:
通信双方的地址:
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-IDATELUIP地址: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 {//创建服务器 指定IPServerSocket 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;}@Overridepublic 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();}}}}}
