【黑马程序员】网络编程——Java复习笔记
来源:互联网 发布:java中printf格式化输 编辑:程序博客网 时间:2024/05/20 08:25
c——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
网络编程
什么是网络编程?
用Java语言实现计算机间数据的信息传递和资源共享
网络编程的三要素
- IP地址:网络中计算机的唯一标识
a:点分十进制 xxx.xxx.xxx.xxx
b:IP地址的组成 网络号段+主机号段
c:InetAddress类 是个没有构造方法的类 用于获取ip等 - 端口
是应用程序的标识。范围:0-65535。其中0-1024不用。 - 协议
UDP:数据打包,每一次不超过64k,不建立连接,效率高,不可靠
TCP:建立数据通道,无限制,效率稍低,可靠
Socket机制
- 通信两端都应该有Socket对象
- 所有的通信都是通过Socket间的IO进行操作的. 网络通信其实就是Socket通信
Socket套接字:网络上具有唯一标识的IP地址和端口号组合在一起构成唯一能识别的标识符套接字
UDP协议发送和接收数据
发送:
import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;/** * Created by mo on 15/11/21. * UDP发送数据 * 创建Socket对象 * 创建数据包 * 发送数据包 * 释放资源 */public class UDPsend { public static void main(String[] args) throws IOException { DatagramSocket datagramSocket = new DatagramSocket(); byte[] arr = "Hello,UDP,我来了".getBytes();// InetAddress address = InetAddress.getByName("192.168.0.100");//接收端ip// int port = 10765;//接收端端口// DatagramPacket datagramPacket = new DatagramPacket(arr,arr.length,address,port); //精简版 DatagramPacket datagramPacket = new DatagramPacket(arr,arr.length,InetAddress.getByName("192.168.0.100"),10765); datagramSocket.send(datagramPacket); datagramSocket.close(); }}
接收:
import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;/** * Created by mo on 15/11/21. * UDP接收数据 * * 创建接收端Socket对象 * 创建数据包(接收数据) * 调用Socket对象的接收方法 * 解包并显示在控制台 * 释放资源 */public class UDPreceive { public static void main(String[] args)throws IOException{ //接收数据要指定端口 DatagramSocket datagramSocket = new DatagramSocket(10765); //创建数据包接收 byte[] arr = new byte[1024]; DatagramPacket datagramPacket = new DatagramPacket(arr,arr.length); //接收数据 datagramSocket.receive(datagramPacket); //解析数据内容// int len = datagramPacket.getLength(); //获取数据实际长度// byte[] received = datagramPacket.getData();//获取数据缓冲区 String s = new String(datagramPacket.getData(),0,datagramPacket.getLength()); //获取对方ip String ip = datagramPacket.getAddress().getHostAddress(); System.out.println(ip+":"+s); datagramSocket.close(); }}
案例1:键盘录入数据 直到录入886 客户端结束输入数据
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;/** * Created by mo on 15/11/21. * 需求:键盘录入数据 直到录入886 客户端结束输入数据 */public class Send { public static void main(String[] args)throws IOException { //这是发送端 System.out.println("请输入要发送的数据"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line ; //创建UDP用的DatagramSocket对象 DatagramSocket datagramSocket = new DatagramSocket(); //读取键盘录入的数据 while ((line = br.readLine())!=null){ if (line.equals("886")){ break;//如果是886则退出循环 } //不是886,则创建数据包并把数据和接受者的端口+ip封装 byte[] arr = line.getBytes(); DatagramPacket datagramPacket = new DatagramPacket(arr,arr.length, InetAddress.getByName("192.168.0.100"),10765); //发送数据包 datagramSocket.send(datagramPacket); } datagramSocket.close(); }}/** * Created by mo on 15/11/21. * 这是接收端 */public class Received { public static void main(String[] args) throws IOException{ //创建接收端DatagramSocket对象,传入端口号 DatagramSocket datagramSocket = new DatagramSocket(10765); //循环接收数据 while (true){ byte[] arr = new byte[1024]; DatagramPacket datagramPacket = new DatagramPacket(arr,arr.length); datagramSocket.receive(datagramPacket); String s = new String(datagramPacket.getData(),0,datagramPacket.getLength()); String ip = datagramPacket.getAddress().getHostAddress(); System.out.println(ip+":"+s); } //接收端应该一直开着 等待接收数据 所以不close }}
案例2:多线程实现接收发送在同一窗口
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;/** * Created by mo on 15/11/21. * 多线程实现接收发送在同一窗口 */public class SendAndReceived { public static void main(String[] args) throws SocketException { //创建接收和发送的Socket对象 DatagramSocket sendSocket = new DatagramSocket(); DatagramSocket receiveSocket = new DatagramSocket(10765); //创建和启动线程 Thread send = new Thread(new SendThread(sendSocket)); Thread receive = new Thread(new ReceiveThread(receiveSocket)); send.start(); receive.start(); }}/** * 这是发送线程类 */class SendThread implements Runnable{ //构造方法接收socket对象 private DatagramSocket datagramSocket; public SendThread(DatagramSocket datagramSocket) { this.datagramSocket = datagramSocket; } @Override public void run() { //键盘录入数据 System.out.println("请输入要发送的数据"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line ; try { while ((line = br.readLine())!=null){ //如果输入的是886则退出循环 if (line.equals("886")){ break; } //将输入的数据转为字节数组,然后封装到数据包并发送 byte[] arr = line.getBytes(); DatagramPacket datagramPacket = new DatagramPacket(arr,arr.length, InetAddress.getByName("192.168.0.100"),10765); datagramSocket.send(datagramPacket); } } catch (IOException e) { e.printStackTrace(); } datagramSocket.close(); }}/** * 这是接收线程类 */class ReceiveThread implements Runnable{ private DatagramSocket datagramSocket; public ReceiveThread(DatagramSocket datagramSocket) { this.datagramSocket = datagramSocket; } @Override public void run() { while (true){ byte[] arr = new byte[1024]; //创建接收用的数据包 DatagramPacket datagramPacket = new DatagramPacket(arr,arr.length); //接收数据包 try { datagramSocket.receive(datagramPacket); } catch (IOException e) { e.printStackTrace(); } //解析数据包 String s = new String(datagramPacket.getData(),0,datagramPacket.getLength()); //获取发送者的ip String ip = datagramPacket.getAddress().getHostAddress(); System.out.println(ip+":"+s); } }}
TCP协议发送和接收数据
发送:
import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;/** * Created by mo on 15/11/21. * * TCP发送数据 * 创建发送端的Socket * 如果创建成功 就说明连接已建立 * 获取输出流写数据 * 释放资源 */public class ClientDemo { public static void main(String[] args) throws IOException{// Socket socket = new Socket(InetAddress.getByName("192.168.0.100",10888)); //太复杂了,简化一下 Socket socket = new Socket("192.168.0.100",10888); OutputStream os = socket.getOutputStream(); os.write("hello,TCP,我来了".getBytes()); //客户端接收服务器端的反馈 InputStream is = socket.getInputStream(); byte[] arr = new byte[1024]; int len = is.read(arr); String s = new String(arr,0,len); System.out.println(s); //关闭Socket socket.close(); }}
接收:
import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;/** * Created by mo on 15/11/21. * * TCP接收数据 * 创建接收端的ServerSocket * 监听客户端,返回一个对应的Socket对象 * 获取输入流,读取数据并显示 * 释放资源 */public class ServerDemo { public static void main(String[] args) throws IOException { ServerSocket ss = new ServerSocket(10888); //监听,并接收到此套接字的连接,此方法在连接传入前一直阻塞 Socket s = ss.accept(); //获取数据 InputStream is = s.getInputStream(); byte[] arr = new byte[1024]; int len = is.read(arr);//阻塞式方法 String str = new String(arr, 0, len); System.out.println(s.getInetAddress().getHostAddress() + ":" + str); //服务器向客户端发送反馈,上面的read是阻塞式,所以不用担心上面还没执行完就执行下面 OutputStream os = s.getOutputStream(); os.write("服务器已收到信息".getBytes()); //关闭客户端的Socket s.close();// ss.close();//服务器要保持开启 不能关 }}
案例1:客户端键盘录入,服务器输出到控制台
客户端
import java.io.*;import java.net.Socket;/** * Created by mo on 15/11/21. */public class Client { public static void main(String[] args) throws IOException { Socket socket = new Socket("192.168.0.100", 10588); //创建线程用于接收服务端发来的反馈 Thread rec = new Thread(new Receive(socket)); rec.start(); //键盘录入 BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); //把通道内的流给包装一下.因为Socket走的是字节流OutputStream BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); String line; while ((line = bf.readLine()) != null) { if (line.equals("886")){ break; } bw.write(line); bw.newLine(); bw.flush(); } //这里也可以采用字节流,但要保证发送端接收端都用的字节流(具体代码为以下注释部分)// BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));// OutputStream bw = socket.getOutputStream();//// String line;//// while ((line = bf.readLine()) != null) {// if (line.equals("886")){// break;// }// bw.write(line.getBytes());//// } //关闭Socket rec.interrupt(); socket.close(); }}/** * 这是用于接收服务器端发来的反馈的线程类 */class Receive implements Runnable{ //构造方法接收Socket对象 private Socket socket ; public Receive(Socket socket) { this.socket = socket; } @Override public void run() { while (true){ //判断Socket连接是否被关闭 if (socket.isClosed()){ break; } //连接还存在就开始等待接收反馈 InputStream is; byte[] arr = new byte[1024]; int len; try { is = socket.getInputStream(); len = is.read(arr);//阻塞式方法 System.out.println(new String(arr,0,len)); } catch (IOException e) { System.out.println("已退出聊天室");//输入886退出后捕获并处理异常 } } }}
服务端
import java.io.*;import java.net.ServerSocket;import java.net.Socket;/** * Created by mo on 15/11/21. * 客户端键盘录入,服务器输出到控制台 */public class Server { public static void main(String[] args) throws IOException { ServerSocket ss = new ServerSocket(10588); //在循环里监听并建立Socket连接 while (true){ Socket s = ss.accept(); //把通道内的流给包装一下.因为Socket走的是字节流 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); String line ; //IO流获取数据并给予反馈 while ((line = br.readLine()) != null){ System.out.println(s.getInetAddress().getHostAddress()+":"+line); OutputStream os = s.getOutputStream(); os.write("服务器已接收到信息".getBytes()); } s.close(); } //这里也可以采用字节流,但要保证发送端接收端都用的字节流(具体代码为以下注释部分)// while (true){// Socket s = ss.accept();// InputStream br=s.getInputStream();//// int line ;// byte[] arr = new byte[1024];// while ((line = br.read(arr)) != -1){// System.out.println(s.getInetAddress().getHostAddress()+":"+new String(arr,0,line));// OutputStream os = s.getOutputStream();// os.write("服务器已接收到信息".getBytes());// }//// s.close();// } }}
案例2:多个客户端上传文件到服务器(多线程解决)
服务器端
import java.io.*;import java.net.ServerSocket;import java.net.Socket;/** * Created by mo on 15/11/21. * * 只用while(true)包起来的缺点:都以一个名称储存 前几个客户端传的被覆盖 只剩最后一个 * * 所以要用多线程 */public class Server { public static void main(String[] args) throws IOException { //创建ServerSocket对象 ServerSocket serverSocket = new ServerSocket(25255); //因为不知道有多少个客户端发送数据,所以这里用while循环监听并为每一个建立连接的客户端启动一个新线程 //接收文件的代码放在线程里处理 while (true) { Socket s = serverSocket.accept(); Thread thread = new Thread(new serverThread(s)); thread.start(); } }}/** * 这是服务端接收文件的线程类 */class serverThread implements Runnable { private Socket s; public serverThread(Socket s) { this.s = s; } @Override public void run() { byte[] arr = new byte[4096]; int len; try { BufferedInputStream br = new BufferedInputStream(s.getInputStream()); //这里 多个线程 会覆盖一个文件 所以要改进// BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("account.txt")); //改进方法:因为目前无法获取到上传的文件名,所以只能用当前时间毫秒值来命名 String newName = System.currentTimeMillis()+".txt"; BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream(newName)); while ((len = br.read(arr)) != -1) { bw.write(arr, 0, len); //重点!这里非常有必要flush()一下,不然会导致,最后一次没有接收,丢失最后一部分 bw.flush(); } //保存完毕后给予客户端反馈 OutputStream sd = s.getOutputStream(); sd.write("文件上传完毕".getBytes()); bw.close(); s.close(); } catch (IOException e) { e.printStackTrace(); } }}
客户端(每个客户端都一样,这里只放一个客户端的代码)
import java.io.*;import java.net.Socket;/** * Created by mo on 15/11/21. * * 多个客户端 1个服务器端 * * 客户端不用修改 只修改服务器端 */public class Client1 { public static void main(String[] args)throws IOException { //创建Socket对象 传入目标ip+端口 Socket socket = new Socket("192.168.0.100",25255); //封装要上传的文件 BufferedInputStream br = new BufferedInputStream(new FileInputStream("/Users/mo/account.txt")); //获取通道的写入流 BufferedOutputStream bw = new BufferedOutputStream(socket.getOutputStream()); int len; byte[] arr = new byte[4096]; while ((len=br.read(arr)) != -1){ bw.write(arr,0,len); //重点!这里非常有必要flush()一下,不然会导致,最后一次没有发送出去,导致传过去的文件丢失一部分 bw.flush(); } //上传完了就给个结束标记,告诉服务器已经传完了,别等了 socket.shutdownOutput(); //接收服务器端发来的反馈 InputStream rec = socket.getInputStream(); int end ; byte[] arr1 = new byte[1024]; end = rec.read(arr1); System.out.println(new String(arr1,0,end)); br.close(); socket.close(); }}
0 0
- 【黑马程序员】网络编程——Java复习笔记
- 黑马程序员—java基础复习—网络编程
- 黑马程序员------网络编程复习笔记
- 黑马程序员——学习笔记10.Java网络编程
- 黑马程序员 java学习笔记——网络编程
- 黑马程序员——JAVA笔记之网络编程
- 黑马程序员——java学习笔记--网络编程
- 黑马程序员java学习笔记——网络编程
- 黑马程序员——Java中网络编程笔记
- 黑马程序员——Java网络编程-整理笔记
- 黑马程序员Java笔记——网络编程
- 黑马程序员——java复习总结——GUI和网络编程
- 黑马程序员—网络编程笔记
- 黑马程序员--JAVA基础复习之网络编程
- 黑马程序员--java基础复习之网络编程
- 黑马程序员——Java网络编程
- 黑马程序员——java网络编程
- 黑马程序员——java网络编程
- c语言之素数距离问题
- Struts2:在Interceptor中获取action中的参数值
- 用ArrayList存储数据实现队列功能(写着玩的)
- 不忘初心
- Android-获取GPS数据方法
- 【黑马程序员】网络编程——Java复习笔记
- linux 常用命令
- Makefile下 $(wildcard $^),$^,$@,$?,$<,$(@D),$(@F)
- 10007---Java中从控制台输入数据的几种常用方法
- POJ2407 欧拉函数
- elasticsearch相关配置
- C语言中static关键字的神奇之处
- SurfaceView的了解
- Java实现URI参数签名算法,确保应用与REST服务器之间的安全通信,防止Secret Key盗用、数据篡改等恶意攻击行为