网络编程
一、网络通信的两个要素
- 通信双方的地址:IP地址和端口号
- 网络通信协议:TCP、UDP等协议
二、IP地址InetAddress
-
唯一定位一台网路计算机
-
本机localhost:127.0.0.1
-
IP地址分类:
- ipv4/ipv6
- ipv4:4个字节组成,127.0.0.1。0~255
- ipv6:128位,8个无符号整数
- 公网(互联网)/私网(局域网)
- 互联网:ABCD类地址
- 局域网:192.168.xx.xx 专门给组织内部使用
- ipv4/ipv6
-
域名:因为IP不方便记忆!
-
代码
import java.net.InetAddress; import java.net.UnknownHostException; public class TestIP { public static void main(String[] args) { try { //查询本机地址 InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1"); System.out.println(inetAddress1); //查询网站地址 InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com"); System.out.println(inetAddress2); //常用方法 System.out.println(inetAddress2.getCanonicalHostName());//获得规范名字 System.out.println(inetAddress2.getHostAddress());//获得主机名字 System.out.println(inetAddress2.getHostName());//获得域名 } catch (UnknownHostException e) { e.printStackTrace(); } } }
三、端口Port
端口表示计算机上的一个程序的进程
-
不同的进程有不同的端口号,用来区分软件
-
被规定0-65535
-
单个协议下端口不能冲突
-
端口分类
- 共有端口:0-1023
- HTTP:80
- HTTPS:443
- FTP:21
- SSH:22
- Telent:23
- 程序注册端口:2014-49151,分配给用户或者程序
- Tomcat:8080
- MySQL:3306
- Oracle:1521
- 动态端口,私有:49152-65535
- 共有端口:0-1023
-
常用命令
netstat -ano #查看所有的端口 netstat -ano|findstr "5900" #查看指定端口 tasklist|findstr "8696" #查看指定端口的进程
-
代码
import java.net.InetSocketAddress; public class TestPort { public static void main(String[] args) { InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1",8080); System.out.println(inetSocketAddress); //常用方法 System.out.println(inetSocketAddress.getAddress()); System.out.println(inetSocketAddress.getPort()); System.out.println(inetSocketAddress.getHostName()); } }
四、通讯协议
五、TCP
TCP:三次握手(连接),四次挥手(断开)!
1、实现聊天
-
客户端
- 连接服务器
- 发送消息
import java.io.IOException; import java.io.OutputStream; import java.net.Socket; //TCP客户端 public class TCPClient1 { public static void main(String[] args) { Socket socket = null; OutputStream outputStream = null; try { //1、服务器地址 String serverIP = "127.0.0.1"; int port = 9999; //2、创建一个socket连接 socket = new Socket(serverIP, port); //3、发送消息,IO流 outputStream = socket.getOutputStream(); outputStream.write("你好!".getBytes()); } catch (IOException e) { e.printStackTrace(); }finally { //关闭资源 if (outputStream!=null){ try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket!=null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
-
服务端
- 建立服务的端口ServerSocket
- 等待客户端连接accept
- 接收客户端消息
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; //TCP服务端 public class TCPServer1 { public static void main(String[] args) { ServerSocket serverSocket = null; Socket accept = null; InputStream inputStream = null; ByteArrayOutputStream byteArrayOutputStream = null; try { //1、服务器地址 serverSocket = new ServerSocket(9999); while (true){ //2、等待客户端连接 accept = serverSocket.accept(); //3、读取客户端消息 inputStream = accept.getInputStream(); //管道流 byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len=inputStream.read(buffer))!=-1){ byteArrayOutputStream.write(buffer,0,len); } System.out.println(byteArrayOutputStream.toString()); } } catch (IOException e) { e.printStackTrace(); }finally { //关闭资源 if (byteArrayOutputStream!=null){ try { byteArrayOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (inputStream!=null){ try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (serverSocket!=null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } if (accept!=null){ try { accept.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
2、实现文件上传
-
客户端
import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; //客户端 public class TCPClient2 { public static void main(String[] args) throws Exception { InetAddress serverIP = InetAddress.getByName("127.0.0.1"); int port = 9999; //创建socket连接 Socket socket = new Socket(serverIP, port); //创建一个输出流 OutputStream outputStream = socket.getOutputStream(); //读取文件 FileInputStream file = new FileInputStream("1.png"); //写出文件 byte[] buffer = new byte[1024]; int len; while ((len=file.read(buffer))!=-1){ outputStream.write(buffer,0,len); } //通知服务器已经传输完毕 socket.shutdownOutput(); //确定服务器接收完毕 InputStream inputStream = socket.getInputStream(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer2 = new byte[1024]; int len2; while ((len2=inputStream.read(buffer2))!=-1){ byteArrayOutputStream.write(buffer2,0,len2); } System.out.println(byteArrayOutputStream.toString()); //关闭资源 file.close(); outputStream.close(); socket.close(); } }
-
服务端
import java.io.*; import java.net.ServerSocket; import java.net.Socket; //服务端 public class TCPServer2 { public static void main(String[] args) throws IOException { //创建服务 ServerSocket serverSocket = new ServerSocket(9999); //监听客户端的连接:阻塞式监听,会一直等待客户端连接 Socket accept = serverSocket.accept(); //获取输入流 InputStream inputStream = accept.getInputStream(); //文件输出 FileOutputStream fileOutputStream = new FileOutputStream(new File("receive.png")); byte[] buffer = new byte[1024]; int len; while ((len=inputStream.read(buffer))!=-1){ fileOutputStream.write(buffer,0,len); } //通知客户端接收完毕 OutputStream outputStream = accept.getOutputStream(); outputStream.write("服务器接收完毕".getBytes()); //关闭资源 outputStream.close(); fileOutputStream.close(); inputStream.close(); accept.close(); serverSocket.close(); } }
六、UDP
不需要连接服务器,没有客户端和服务器的概念
1、消息发送
-
发送方
import java.net.*; public class UDPClient1 { public static void main(String[] args) throws Exception { InetAddress serverIP = InetAddress.getByName("localhost"); int port = 9999; //1、建立一个socket DatagramSocket datagramSocket = new DatagramSocket(); //2、建立一个包 String msg = "你好!"; DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, serverIP, port); //3、发送一个包 datagramSocket.send(datagramPacket); //4、关闭资源 datagramSocket.close(); } }
-
接收方
import java.net.DatagramPacket;import java.net.DatagramSocket;//UDP没有客户端服务端的概念public class UDPServer1 { public static void main(String[] args) throws Exception { //1、开放端口 DatagramSocket datagramSocket = new DatagramSocket(9999); //2、接收数据包 byte[] buffer = new byte[1024]; DatagramPacket datagramPacket = new DatagramPacket(buffer,0,buffer.length); datagramSocket.receive(datagramPacket);//阻塞接收 System.out.println(datagramPacket.getAddress()); System.out.println(new String(datagramPacket.getData(),0,datagramPacket.getLength())); //3、关闭资源 datagramSocket.close(); }}
2、实现多线程聊天
-
发送方
import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetSocketAddress;public class TalkSend implements Runnable{ DatagramSocket datagramSocket = null; BufferedReader bufferedReader = null; private int fromPort ; private String toIP ; private int toPort; public TalkSend(int fromPort, String toIP, int toPort) { this.fromPort = fromPort; this.toIP = toIP; this.toPort = toPort; try { datagramSocket = new DatagramSocket(fromPort); bufferedReader = new BufferedReader(new InputStreamReader(System.in)); }catch (Exception e){ e.printStackTrace(); } } @Override public void run() { while (true){ try { String s = bufferedReader.readLine(); byte[] data = s.getBytes(); DatagramPacket datagramPacket = new DatagramPacket(data,0,data.length, new InetSocketAddress(this.toIP,this.toPort)); //发送 System.out.println("我:"+s); datagramSocket.send(datagramPacket); if(s.equals("bye")){ break; } }catch (Exception e){ e.printStackTrace(); } } datagramSocket.close(); }}
-
接收方
import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.SocketException;public class TalkReceive implements Runnable{ DatagramSocket datagramSocket = null; private int port; private String msgFrom; public TalkReceive(int port, String msgFrom) { this.port = port; this.msgFrom = msgFrom; try { datagramSocket = new DatagramSocket(port); }catch (SocketException e){ e.printStackTrace(); } } @Override public void run() { while (true){ try { //准备数据 byte[] buffer = new byte[1024]; DatagramPacket datagramPacket = new DatagramPacket(buffer,0,buffer.length); //接收 datagramSocket.receive(datagramPacket);//阻塞式接收包裹 byte[] data = datagramPacket.getData(); String s = new String(data, 0, data.length); System.out.println(msgFrom+":"+s); if(s.equals("bye")){ break; } }catch (Exception e){ e.printStackTrace(); } } datagramSocket.close(); }}
-
对象1
//人员Apublic class Person1 { public static void main(String[] args) { //发送线程 new Thread(new TalkSend(7777,"127.0.0.1",9999)).start(); //接收线程 new Thread(new TalkReceive(8888,"人员B")).start(); }}
-
对象2
//人员2public class Person2 { public static void main(String[] args) { //发送线程 new Thread(new TalkSend(5555,"127.0.0.1",8888)).start(); //接收线程 new Thread(new TalkReceive(9999,"人员A")).start(); }}
七、URL下载网络资源
协议://ip地址:端口/项目名/资源
public class URL1 { public static void main(String[] args) throws MalformedURLException { URL url = new URL("http://localhost:8080/helloworld/index.jsp?username=admin&password=123456"); 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()); //获取参数 }}
import javax.net.ssl.HttpsURLConnection;import java.io.FileOutputStream;import java.io.InputStream;import java.net.URL;import java.net.URLConnection;public class URL2 { public static void main(String[] args) throws Exception { //下载地址 URL url = new URL("https://p4.music.126.net/XrYsBt4yPAuPHL9zNSJtRw==/109951166053214732.jpg?param=34y34"); //连接到资源 URLConnection urlConnection = (HttpsURLConnection)url.openConnection(); // InputStream inputStream = urlConnection.getInputStream(); FileOutputStream fileOutputStream = new FileOutputStream("download.jpg"); byte[] buffer = new byte[1024]; int len; while ((len=inputStream.read(buffer))!=-1){ fileOutputStream.write(buffer,0,buffer.length); } fileOutputStream.close(); inputStream.close(); }}