day26 Java学习 网络编程
网络编程 (概述)
计算机网络:
* 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程:
* 就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
网络编程 (三要素:IP概述 (掌握))
* 每台设备在网络中的唯一标识 。
* 每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个地址。
* ipconfig :查看本机IP
* ping :测试连接
* IPv4 :4个字节组成,4个0-255;已用尽。
* IPv6 :8组,每组4个16进制数。
网络编程 (三要素:端口概述 (掌握))
* 每个程序在设备上的唯一标识 。
* 每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台及其上,还要明确发到那个程序。
* 端口号的范围 :0-----65535
* 编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本都被系统程序占用了。
网络编程 (三要素:协议 (掌握))
* 为计算机网络中进行数据交换而建立的规则,标准或约定的集合。
* UDP :面向无连接,数据不安全,速度快,不区分客户端和服务端。
* TCP : 面向连接 (三次握手),数据安全,速度略慢,分为客户端和服务端。
(三次握手:客户端先向服务端发起请求,服务端响应请求,传输数据)
网络编程 (Socket通信 (了解))
Socket套接字概述:
* 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一的标识符套接字。
* 通信的两端都有Socket。
* 网络通信其实就是Socket间的通信。
* 数据在两个Socket间通过IO流传输。
* Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己锁对应的IP和port。
网络编程 (UDP传输(了解))
1. 发送Send
* 创建DatagramSocket ,随机端口号。
* 创建DatagramPacket , 指定数据 ,长度 ,地址,端口。
* 使用DatagramSocket发送DatagramPacket。
* 关闭DatagramSocket 。
public class Dome1_Send { public static void main(String[] args) throws Exception { String str = "新年快乐"; DatagramSocket socket = new DatagramSocket(); // 创建Socket DatagramPacket packet = // 创建Packet new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 8888); socket.send(packet); // 将数据发出去 socket.close(); System.out.println("aaa"); }
2.接收Receive
* 创建DatagramSocket ,指定端口号。
* 创建DatagramPacket , 指定数组 ,长度 。
* 使用DatagramSocket发送DatagramPacket。
* 关闭DatagramSocket 。
* 从DatagramPacket中获取数据。
public static void main(String[] args) throws IOException { DatagramSocket socket =new DatagramSocket(8888); DatagramPacket packet= new DatagramPacket(new byte [1024], 1024); socket.receive(packet); //接收数据 byte [] arr=packet.getData(); //获取数据 int len=packet.getLength(); //获取有效的字节个数 System.out.println(new String(arr, 0,len)); String ip=packet.getAddress().getHostAddress(); //获取ip int prot=packet.getPort(); //获取端口号 socket.close(); System.out.println(ip); System.out.println(prot); }
、3,接收方获取ip和端口号:
* String ip=packet.getAddress().getHostAddress();
* int prot=packet.getPort();
网络编程 (UPD传输多线程)
* 发送和接收在一个窗口完成。
public class Dome3_MoreThread { public static void main(String[] args) { new Receive().start(); new Send().start(); } } class Receive extends Thread { public void run () { //try catch快捷键 shift + alt + z try { DatagramSocket socket =new DatagramSocket(6566); DatagramPacket packet =new DatagramPacket(new byte[1204], 1204); while (true) { socket.receive(packet); //接收数据 byte [] arr=packet.getData(); //获取数据 int len=packet.getLength(); String ip=packet.getAddress().getHostAddress(); //获取ip int port =packet.getPort(); //获取端口 System.out.println(ip+":"+port+":"+new String(arr,0,len)); } } catch (IOException e) { // 自动生成的 catch 块 e.printStackTrace(); } } } class Send extends Thread{ public void run() { try { Scanner sc = new Scanner(System.in); DatagramSocket socket = new DatagramSocket(); while (true) { String line = sc.nextLine(); if ("完成".equals(line)) { break; } DatagramPacket packet = new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getByName("127.0.0.1"), 6566); socket.send(packet); } socket.close(); } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } }
网络编程 (UPD聊天界面)
public class Dome5_GUIChat2 extends Frame { private TextField tf; private Button send; private Button log; private Button clear; private Button shake; private TextArea viewText; private TextArea sendText; private DatagramSocket socket; private BufferedWriter bw; public Dome5_GUIChat2() { init(); southPanel(); centerPanel(); event(); //关闭窗口 } private void event() { // TODO 自动生成的方法存根 this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { try { socket.close(); bw.close(); } catch (IOException e1) { // TODO 自动生成的 catch 块 e1.printStackTrace(); } // 关闭窗口时,接收也关闭 System.exit(0); } }); send.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { send(); } catch (IOException e1) { // TODO 自动生成的 catch 块 e1.printStackTrace(); } } }); log.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { logFile(); } catch (IOException e1) { // TODO 自动生成的 catch 块 e1.printStackTrace(); } } }); //清空 clear.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { viewText.setText(""); } }); //震动 shake.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO 自动生成的方法存根 try { send(new byte [] {-1}, tf.getText()); } catch (IOException e1) { // TODO 自动生成的 catch 块 e1.printStackTrace(); } } }); //快捷键enter 发送 sendText.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { // TODO 自动生成的方法存根 if (e.getKeyCode()==KeyEvent.VK_ENTER) { try { send(); } catch (IOException e1) { // TODO 自动生成的 catch 块 e1.printStackTrace(); } } } }); } //震动方法 private void shake() { int x=this.getLocation().x; //getLocation():获取坐标 int y=this.getLocation().y; for(int i=0;i<20;i++) { this.setLocation(x+5,y+5); this.setLocation(x+5,y-5); this.setLocation(x-5,y+5); this.setLocation(x-5,y-5); this.setLocation(x,y); } } //记录方法 private void logFile() throws IOException { bw.flush(); //刷新缓冲区 FileInputStream fis=new FileInputStream("config.txt"); //读取文件 ByteArrayOutputStream baos=new ByteArrayOutputStream(); //在内存中创建缓存区 int len; byte [] arr=new byte[8192]; while ((len=fis.read(arr))!=-1) { baos.write(arr, 0, len); } String str=baos.toString(); //将内存中的内容转成字符串 viewText.setText(str); fis.close(); } // 重载方法 private void send(byte[] arr,String ip) throws IOException { DatagramPacket packet= new DatagramPacket(arr, arr.length,InetAddress.getByName(ip), 7777); socket.send(packet); //发送数据 } //发送按钮 private void send() throws IOException { String message= sendText.getText(); //获取发送区域的内容 String ip= tf.getText(); //获取id地址 send(message.getBytes(), ip); String time =getCurrentTime(); String str = time+"我对"+ip+"说:\r\n"+message+"\r\n\r\n"; viewText.append(str); //将信息添加到显示区域中 bw.write(str); //将信息写到文本文档中 sendText.setText(""); } private String getCurrentTime() { Date d=new Date(); //获取当前日期对象 SimpleDateFormat sdf=new SimpleDateFormat("yyy年MM月dd日 HH:mm:ss"); return sdf.format(d); } private void centerPanel() { Panel center =new Panel(); //创建中间的panel viewText = new TextArea(); sendText = new TextArea(5,1); center.setLayout(new BorderLayout()); //设置为边界布局管理器 center.add(sendText,BorderLayout.SOUTH); //发送的文本区域在南边 center.add(viewText,BorderLayout.CENTER); //显示的文本区域在中间 viewText.setEditable(false); //setEditable():设置文本是否可以编辑 viewText.setBackground(Color.WHITE); // setBackground():设置背景颜色 sendText.setFont(new Font("xxx",Font.PLAIN, 16)); //setFont():设置字体大小 viewText.setFont(new Font("xxx",Font.PLAIN, 16)); this.add(center,BorderLayout.CENTER); } private void southPanel() { Panel south = new Panel(); // 创建南边的Panel (上北下南) tf = new TextField(20); // TextField():创建文本字段存储ip地址(里面参数的列数) tf.setText("127.0.0.1"); tf.setEditable(false); tf.setBackground(Color.WHITE); send = new Button("发送"); log = new Button("记录"); clear = new Button("清屏"); shake = new Button("震动"); south.add(tf); south.add(send); south.add(log); south.add(clear); south.add(shake); this.add(south, BorderLayout.SOUTH); // 将Panel放在Frame的南边 } private void init() { this.setLocation(50, 50); //setLocation():设置坐标 this.setSize(400, 600); //setSize():设置窗口大小 new Receive().start(); try { socket = new DatagramSocket(); bw=new BufferedWriter(new FileWriter("config.txt",true)); } catch (Exception e) { e.printStackTrace(); } this.setVisible(true); //setVisible():设置窗口是否显示 }; private class Receive extends Thread{ public void run() { try { DatagramSocket socket = new DatagramSocket(9999); DatagramPacket packet = new DatagramPacket(new byte[8192], 8192); while (true) { socket.receive(packet); // 接收信息 byte[] arr = packet.getData(); // 获取字节数据 int len = packet.getLength(); // 获取有效字节 String ip = tf.getText(); // 获取id地址 if (arr[0] == -1 && len == 1) { // 如果发过来的数组第一个值存储是-1并且数组长度是1 shake(); // 调用震动方法 viewText.setText(ip+"对方给你发了一个震动"+"\r\n\r\n"); continue; // 终止本次循环,继续下次循环,因为震动后不需要执行下面的代码 } String message = new String(arr, 0, len); // 转换成字符串 String time = getCurrentTime(); String str = time + "\t" + ip + "对我说:" + "\t\n" + message + "\r\n\r\n"; viewText.append(str); bw.write(str); } } catch (Exception e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } public static void main(String[] args) { new Dome5_GUIChat2(); } }
网络编程 (TCP协议(掌握))
1.客户端:
* 创建Socket连接服务端(指定ip地址,端口号)通过ip地址找到对应的服务器。
* 调用Socket的getInputStream()和getOutputStream()方法获取和服务器相连的IO流。
* 输入流可以读取服务端输出流写出的数据。
* 输出流可以写出数据到服务端的输入流
public static void main(String[] args) throws IOException { /* 2.服务端: * 创建ServerSocket(需要指定端口号); * 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket。 * 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流。 * 输入流可以读取客户端输出流写出的数据。 * 输出流可以写出数据到客户端的输入流 */ ServerSocket server=new ServerSocket(12345); Socket socket=server.accept(); //接收客户端请求 BufferedReader br= new BufferedReader(new InputStreamReader(socket.getInputStream()));//将字节流包装成了字符流 PrintStream ps=new PrintStream(socket.getOutputStream()); //PrintStream中有写出换行的方法 ps.println("噶"); System.out.println(br.readLine()); ps.println("哦买噶"); System.out.println(br.readLine()); socket.close(); }
2.服务端:
* 创建ServerSocket(需要指定端口号);
* 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket。
* 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流。
* 输入流可以读取客户端输出流写出的数据。
* 输出流可以写出数据到客户端的输入流
public static void main(String[] args) throws IOException { /* 2.服务端: * 创建ServerSocket(需要指定端口号); * 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket。 * 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流。 * 输入流可以读取客户端输出流写出的数据。 * 输出流可以写出数据到客户端的输入流 */ ServerSocket server=new ServerSocket(12345); Socket socket=server.accept(); //接收客户端请求 BufferedReader br= new BufferedReader(new InputStreamReader(socket.getInputStream()));//将字节流包装成了字符流 PrintStream ps=new PrintStream(socket.getOutputStream()); //PrintStream中有写出换行的方法 ps.println("噶"); System.out.println(br.readLine()); ps.println("哦买噶"); System.out.println(br.readLine()); socket.close(); }
网络编程 (服务端是多线程的:(掌握))
public static void main(String[] args) throws IOException { ServerSocket server=new ServerSocket(12345); while (true) { final Socket socket=server.accept(); //接收客户端请求 new Thread() { public void run() { try { BufferedReader br= new BufferedReader(new InputStreamReader(socket.getInputStream()));//将字节流包装成了字符流 PrintStream ps=new PrintStream(socket.getOutputStream()); //PrintStream中有写出换行的方法 ps.println("噶"); System.out.println(br.readLine()); ps.println("哦买噶"); System.out.println(br.readLine()); socket.close(); } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } }; }