通信数据源有哪些 文件、byteArrayOutputStream、socke管道、控制台1. 基础概念1. 地址Ip地址2. 端口 计算机中区分不同进程同一个协议下,端口不能重复使用不同协议可以1024以下端口预留给系统的 比如http 80 ftp 21URL: 统一资源定位符组成协议主机域名端口资源文件名3. 数据传输协议tcp 协议 三次握手面向连接数据流打电话数据不会丢失udp 协议 发短信 数据可能都是协议分成网络通信封装1. 数据封装发送数据应用层 http,ftp,snmp 都是应用层协议传输层 端口 tcp/udp 传输层协议具体数据包结构百度网络层 Ip具体数据包结构百度数据连接层 Mac地址2. 数据拆分 数据接收2. 地址 Api 基础 使用InetAddress 封装IP地址和域名InetSocketAddress 封装IP和端口URL 统一资源定位符组成 协议主机域名端口资源文件名通过 URL 获取资源网络爬虫2.1.InetAddress 封装IP地址和域名public static void main(String[] args) throws URISyntaxException, IOException { /** * InetAddress 封装IP地址和域名 */ InetAddress addr InetAddress.getLocalHost(); System.out.println(addr.getHostAddress()); // 获取本机Ip,192.168.2.208 System.out.println(addr.getHostName()); // 获取计算机名 addr InetAddress.getByName(www.baidu.com); System.out.println(addr.getHostAddress()); //根据域名返回Ip addr InetAddress.getByName(182.61.200.6); System.out.println(addr.getHostAddress()); System.out.println(addr.getHostName()); // 如果Ip地址不存在或者dns不解析返回Ip否则返回域名 }2.2.InetSocketAddress 封装IP和端口public static void main(String[] args) throws URISyntaxException, IOException { /** * 封装IP和端口 */ // InetSocketAddress addr1new InetSocketAddress(127.0.0.1,8888); // System.out.println(addr1.getAddress()); // // System.out.println(addr1.getHostName()); // System.out.println(addr1.getPort()); }2.3. URL 统一资源定位符组成 协议主机域名端口资源文件名public static void main(String[] args) throws URISyntaxException, IOException { /** * URL: 统一资源定位符 组成 协议主机域名端口资源文件名 */ // URL urlnew URL(http://www.baidu.com:8080/myServlet?usernamexiaoming); // System.out.println(协议:url.getProtocol()); // System.out.println(主机名:url.getHost()); // System.out.println(端口:url.getPort()); // System.out.println(资源url.getFile()); // System.out.println(相对路径url.getPath()); // System.out.println(锚点url.getRef()); // System.out.println(参数 url.getQuery()); /** * 协议:http 主机名:www.baidu.com 端口:8080 资源/myServlet?usernamexiaoming 相对路径/myServlet 锚点null 参数usernamexiaoming */ // 类似File相对路径 URL url1 new URL(http://baidu.com:8080/a/); URL url2 new URL(url1, b.txt); System.out.println(url2:url2.toString()); //http://baidu.com:8080/a/b.txt }2.4. 通过 URL 获取资源网络爬虫public static void main(String[] args) throws URISyntaxException, IOException { /** * 资源访问 通过流, 模仿网络爬虫, 爬虫网页 保持 到本地 */ URL url3new URL(http://www.baidu.com); InputStream inputStreamurl3.openStream(); BufferedReader readernew BufferedReader( new InputStreamReader(inputStream,utf-8)); String msgnull; BufferedWriter bwnew BufferedWriter( new OutputStreamWriter( new FileOutputStream(baidu.html),utf-8)); while(( msgreader.readLine())!null) { bw.append(msg); bw.newLine(); System.out.println(msg); } bw.flush(); bw.close(); reader.close(); }3. Udp通信3.1. 发送字符串UdpServer 端:3.2.发送基本数据类型比如子弹个数发送【把double转化为内存中double,不是字符串, Double在内存中存储字符串在内存中是逐个字符的ASCII码存储的】package com.denganzhi.pp; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; public class UdpServer { public static void main0001(String[] args) throws IOException { // 1. 创建 服务端 Ip 端口 DatagramSocket servernew DatagramSocket(8888,InetAddress.getByName(localhost)); // 2. 准备接受数据容器 byte[] containernew byte[1024]; // 3. 封装包 DatagramPacket packetnew DatagramPacket(container,container.length); // 4. 接收数据 server.receive(packet); // 5.分析数据 byte[] datapacket.getData(); int len packet.getLength(); System.out.println(new String(data,0,len)); // 6. 释放 server.close(); } public static void main(String[] args) throws IOException { // 1. 创建 服务端 Ip 端口 DatagramSocket servernew DatagramSocket(8888,InetAddress.getByName(localhost)); // 2. 准备接受数据容器 byte[] containernew byte[1024]; // 3. 封装包 DatagramPacket packetnew DatagramPacket(container,container.length); // 4. 接收数据, 阻塞 System.out.println(udp阻塞); server.receive(packet); System.out.println(udp接收数据); // 5.分析数据 Double result convert(packet.getData()); System.out.println(result:result); // 6. 释放 server.close(); } // >UdpClient 端package com.denganzhi.pp; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketException; import java.net.UnknownHostException; public class UdpClient { /** * 字符串 发送 * param args * throws IOException */ public static void main001(String[] args) throws IOException { // 1. 创建 客户端 端口 DatagramSocket clientnew DatagramSocket(6666,InetAddress.getByName(localhost)); // 2. 数据准备 String msgudp编程; byte[] data msg.getBytes(); //3. 打包( 发送地点以及 端口) 打包直接发送所有udp有丢包可能 DatagramPacket packetnew DatagramPacket(data, data.length,new InetSocketAddress(127.0.0.1,8888)); // 4. 发送数据 client.send(packet); // 5. 关闭资源 client.close(); } /** * 基本数据类型 的传输 * param args * throws IOException */ public static void main(String[] args) throws IOException { // 1. 创建 客户端 端口 DatagramSocket clientnew DatagramSocket(6666,InetAddress.getByName(localhost)); // 2. 数据准备 byte[] data convert(11.01); //3. 打包( 发送地点以及 端口) DatagramPacket packetnew DatagramPacket(data, data.length,new InetSocketAddress(127.0.0.1,8888)); // 4. 发送数据 client.send(packet); // 5. 关闭资源 client.close(); } public static byte[] convert(double num) throws IOException { byte[] datanull; ByteArrayOutputStream bosnew ByteArrayOutputStream(); DataOutputStream dosnew DataOutputStream(bos); dos.writeDouble(num); dos.flush(); data bos.toByteArray(); dos.close(); return data; } }4. Tcp通信4.1. TcpServer 发送字符串、发送基本数据类型,直接写DataInputStream服务端package com.denganzhi.pp; import java.io.BufferedWriter; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; public class TcpServer { public static void main(String[] args) throws IOException { //1.. 创建服务器, 指定端口 ServerSocket servernew ServerSocket(8888); // 2. 指定客户端 阻塞式 // 完成 三次握手 , 建立管道 System.out.println(服务器阻塞,等待客户端连接); Socket socket server.accept(); System.out.println(一个客户端建立连接); // 服务端输出数据 // BufferedWriter bwnew BufferedWriter( // new OutputStreamWriter(socket.getOutputStream())); // // 必须 有行 结束符socket内存数据才可以被写出 // String str我是来自服务器; // bw.write(str); // bw.newLine(); // 必须有 // bw.flush(); // 直接写出基本数据类型比如游戏中子弹个数 DataOutputStream dosnew DataOutputStream( socket.getOutputStream()); dos.writeDouble(11.01); dos.flush(); } }客户端实现package com.denganzhi.pp; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; import java.net.UnknownHostException; public class TcpClient { public static void main(String[] args) throws UnknownHostException, IOException { //1. 创建客户端 必须指定要连接的 服务器 // tcp 客户端端口有系统分配 Socket clinetnew Socket(localhost,8888); //BufferedReader readernew BufferedReader( // new InputStreamReader( // clinet.getInputStream())); // //String echo reader.readLine(); // //System.out.println(echo); DataInputStream disnew DataInputStream(clinet.getInputStream()); double result dis.readDouble(); System.out.println(result:result); } }5. Tcp实现聊天实现要点 1. 客户端可以发送数据 必须要把收发数据放入不同的线程中2. 服务器实现多个连接客户端监听服务器必须受到数据才发送数据到客户端所以服务器必须把不同客户端放入独立的线程中代码流程1.Client: 1. 实现客户端上线功能 为每一个客户端接发数据启动一个线程Server: 1. 这里实现客户端上线功能为每一个客户端通道启动一个线程 把任务我放入List中2.Client 客户端A发送数据Server 服务器A通道线程接收数据服务器sendOthers() 发送给List中其他任务线程如果是群聊遍历List发送即可如果是私聊在List找到对应 线程通道根据name ,send即可实现功能 群聊、 私聊 test:您好版本1服务器代码支持客户A发送到服务器服务器回客户端A,服务器只是支持一个客户端package com.denganzhi.multi; import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; public class TcpServer { public static void main(String[] args) throws IOException { //1.. 创建服务器, 指定端口 ServerSocket servernew ServerSocket(8888); // 2. 指定客户端 阻塞式 // 完成 三次握手 , 建立管道 System.out.println(服务器阻塞,等待客户端连接); // while(true) { // 服务器实现多线程,多个客户端连接 Socket socket server.accept(); System.out.println(一个客户端建立连接); DataInputStream disnew DataInputStream(socket.getInputStream()); DataOutputStream dosnew DataOutputStream( socket.getOutputStream()); while(true) { // 读取客户端数据 String msg dis.readUTF(); System.err.println(服务收到数据:msg); // 服务器输出数据 dos.writeUTF(服务器输出数据120); dos.flush(); } // } } }版本2服务器代码支持群聊私聊版本package com.denganzhi.multi; import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; public class TcpServer { ListMyChannel allChannelsnew ArrayList(); public static void main(String[] args) throws IOException { new TcpServer().start(); } public void start() throws IOException { //1.. 创建服务器, 指定端口 ServerSocket servernew ServerSocket(8888); // 2. 指定客户端 阻塞式 // 完成 三次握手 , 建立管道 System.out.println(服务器阻塞,等待客户端连接); while(true) { // 服务器实现多线程,多个客户端连接 Socket socket server.accept(); System.out.println(一个客户端建立连接); // 服务器接发数据放入一个线程中 MyChannel myChannelnew MyChannel(socket); // 把通过的客户端连接任务装起来 allChannels.add(myChannel); new Thread(myChannel).start(); } } class MyChannel implements Runnable{ boolean isRunningtrue; DataInputStream disnull; DataOutputStream dosnull; private String name; public MyChannel(Socket clinet) { try { dis new DataInputStream(clinet.getInputStream()); dosnew DataOutputStream( clinet.getOutputStream()); String name dis.readUTF(); this.name name; // 1. 这里实现客户端上线功能,为每一个Runnable分配一个name System.out.println(name进入聊天室); this.send(欢迎自己this.name 欢迎进入聊天室); this.sendOthers(通知this.name 进入聊天室); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); CloseUtils.closeAll(dis,dos); isRunningfalse; allChannels.remove(this); } } Override public void run() { while(isRunning) { // 读取客户端数据 ,实现私聊功能 // String msgreceive(); // send(msg); // 实现群聊 sendOthers(); } } public String receive() { String msg; try { msg dis.readUTF(); System.err.println(this.name发送过来数据-----》 服务收到数据:msg); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); CloseUtils.closeAll(dis,dos); isRunningfalse; allChannels.remove(this); } return msg; } // 发送数据 public void send(String msg) { // 服务器输出数据 try { /// dos.writeUTF(服务器输出数据120); dos.writeUTF(msg); dos.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); CloseUtils.closeAll(dis,dos); isRunningfalse; allChannels.remove(this); } } public void sendOthers() { String msg receive(); // test:您好 // 判断私聊还是群聊 if(msg.startsWith()) { // 在容器中知道对应的人 String name msg.substring(1,msg.indexOf(:)); // substring 左 关闭右 开 String content msg.substring(msg.indexOf(:)1); for (MyChannel myChannel : allChannels) { if(myChannel.name.equals(name)) { myChannel.send(this.name私聊 你: content ); } } }else { // 发送给所有人 for (MyChannel myChannel : allChannels) { if(myChannelthis) { continue; } // 发送给其他客户客户端 myChannel.send(群发消息: msg); } } } public void sendOthers(String msg) { for (MyChannel myChannel : allChannels) { if(myChannelthis) { continue; } // 发送给其他客户客户端 myChannel.send(msg); } } } }客户端代码package com.denganzhi.multi; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner; import javax.swing.plaf.ColorChooserUI; public class TcpClient { static boolean cIsRunningtrue; static boolean sIsRunningtrue; public static void main(String[] args) throws UnknownHostException, IOException { //1. 创建客户端 必须指定要连接的 服务器 // tcp 客户端端口有系统分配 Socket clinetnew Socket(localhost,8888); // 客户端 写数据 // 2. 客户端接收、发送消息位于不同线程中 new Thread(new Runnable() { boolean isFirsttrue; Override public void run() { while(cIsRunning) { DataOutputStream dosnull; if(isFirst) { // 1. 客户端上线功能 System.out.println(请输入用户名:); }else{ System.out.println(请输入用发送信息:); } isFirstfalse; Scanner scnew Scanner(System.in); String sendMsg sc.next(); //BufferedReader scnew BufferedReader(new InputStreamReader(System.in)); try { // String sendMsg sc.readLine(); if(sendMsgnull sendMsg! sendMsg.trim()!) { return ; } dos new DataOutputStream(clinet.getOutputStream()); // dos.writeUTF(客户端写入服务器数据110); dos.writeUTF(sendMsg); dos.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); cIsRunning false; // 出异常了停止发送数据 CloseUtils.closeAll(dos); } } } }).start(); // 2. 客户端接收、发送消息位于不同线程中 new Thread(new Runnable() { Override public void run() { // TODO Auto-generated method stub while(sIsRunning) { DataInputStream disnull; try { dis new DataInputStream(clinet.getInputStream()); String result dis.readUTF(); System.err.println(服务端回的数据:result); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); sIsRunningfalse; CloseUtils.closeAll(dis); } } } }).start(); } }CloseUtils 工具类package com.denganzhi.multi; import java.io.Closeable; import java.io.DataOutputStream; import java.io.IOException; public class CloseUtils { // 可变参数 工具类关闭流 // 规则 如果有其他参数只能在最后一个位置,处理方式和数组一致 // public static void closeAll(Closeable ... io){ for (Closeable closeable : io) { if(closeable!null){ try { closeable.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }Server服务端终端控制台输出ClientA客户端控制台输出ClientB客户端控制台输出源码地址https://download.csdn.net/download/dreams_deng/12305064