ch6.Java多线程开发

6.1 进程与线程的概念

进程(Process):操作系统中能够“同时”运行的多个应用程序(QQ、浏览器、Word、WPS)。

线程(Thread):一个应用程序中,能够“同时”运行的多个任务,比如在线播放(一边下载,一边播放),很多软件都支持线程功能,如QQ可以一边接收信息、一边用户可以发送信息,抖音可以一边下载、一边播放。

两者实际上在底层是“分时”(时间片轮转),由操作系统决定。

针对Java语言,我们讲解线程。

6.2 实现线程的两种方法

6.2.1 方法一

  • 让需要实现线程的类,继承java.lang.Thread类;
  • 将需要实现线程的代码,放在从Thread类中重写的run函数里面;
  • 开启线程,用线程对象的start方法。
class Downloader extends Thread{         //①第一步:继承Threadpublic void run() {                   //②第二步:重写run函数for(int i=1;i<=10;i++){try{Thread.sleep(1000);      //休息1秒} catch(Exception ex){}  System.out.println("下载进度:"+i*10+"%");}     }
}
class Player extends Thread{public void run(){for(int i=1;i<=10;i++){try{  Thread.sleep(1000);  } catch(Exception ex){}  System.out.println("播放进度:"+i*10+"%");}    }
}
class ThreadTest{public static void main (String[] args) {Downloader d = new Downloader();Player p = new Player();d.start();     p.start();    //③第三步:用start方法开启各个线程的run函数}
}

当要在执行某个线程一段时间后执行另一个进程时,可用以下代码:

class Downloader extends Thread{         //①第一步:继承Threadpublic void run() {                   //②第二步:重写run函数for(int i=1;i<=10;i++){try{  Thread.sleep(1000);  } catch(Exception ex){}  System.out.println("下载进度:"+i*10+"%");if(i==2){                   //一个线程调用另一个线程new Player().start();}}        }
}
class Player extends Thread{public void run(){for(int i=1;i<=10;i++){try{  Thread.sleep(1000);  } catch(Exception ex){}  System.out.println("播放进度:"+i*10+"%");}    }
}
class ThreadTest{public static void main (String[] args) {Downloader d = new Downloader();     d.start();      //③第三步:用start方法开启各个线程的run函数}
}

6.2.2 方法二

  • 让需要实现线程的类,继承java.lang.Runnable接口;
  • 将需要实现线程的代码,放在从Runnable接口中重写的run函数里面;
  • 实例化线程,将类的对象传入线程的构造函数,再调用线程的start方法。
class Downloader implements Runnable{     //①第一步:实现Runnablepublic void run() {                     //②第二步:重写run函数for(int i=1;i<=10;i++){try{  Thread.sleep(1000);  } catch(Exception ex){}  System.out.println("下载进度:"+i*10+"%");}        }
}
class Player implements Runnable{public void run(){for(int i=1;i<=10;i++){try{  Thread.sleep(1000);  } catch(Exception ex){}  System.out.println("播放进度:"+i*10+"%");}   }
}
class ThreadTest{public static void main (String[] args) {Downloader d = new Downloader();      Thread th1 = new Thread(d);Player p = new Player();            Thread th2 = new Thread(p);      th1.start();    th2.start();     //③第三步:实例化线程,将类的对象传入线程的构造函数,再调用线程的start方法}
}

用了多线程,多个任务完成得比以前快,不是因为多线程让CPU运行更快,是让CPU的利用率提高。

6.3 线程控制

  • 线程开启(start)
  • 线程暂停(suspend)
  • 线程继续(resume)
  • 线程结束(run函数运行完毕)

【例】下载文件,下载到30%,暂停下载5秒,5秒后继续下载,编写代码实现该功能。

class Downloader extends Thread{ public void run() { for(int i=1;i<=10;i++){try{  Thread.sleep(1000);  } catch(Exception ex){}  System.out.println("下载进度:"+i*10+"%");}      }
}
class ThreadTest{public static void main (String[] args) throws Exception {Downloader d = new Downloader();d.start();  Thread.sleep(3200);d.suspend();Thread.sleep(5000);d.resume();}
}

【注意】suspend、resume是不建议使用的函数,有死锁倾向

这两个函数,特别是suspend,在暂停时不会释放线程中的资源,导致资源被该线程长期持有,别人不能使用,故可能造成循环等待。所以不建议使用。可采用以下方法:线程暂停,就让该线程结束(run函数运行完毕);线程继续,新开启一个线程(start)。

class Downloader extends Thread{ boolean RUN = true;static int i = 1;public void run() {   for(;i<=10&&RUN;i++){try{  Thread.sleep(1000);  } catch(Exception ex){}  System.out.println("下载进度:"+i*10+"%");}     }
}
class ThreadTest{public static void main (String[] args) throws Exception {Downloader d = new Downloader();d.start();  Thread.sleep(3000);d.RUN = false;Thread.sleep(5000);d = new Downloader();     //新开启一个线程继续d.start();}
}

6.4 线程同步

  • 主要出现在“多个线程访问同一内存资源的场合”,如:下载文件时,如果同时开多个线程下载文件,可以提高下载速度
  • 解决同步问题:用synchronized原子代码包含起来,保证其要么全部运行,要么全部不运行,别的线程在此之间,无法抢占CPU
    这种方式。实际上,是将线程功能进行了退化,“几乎又变成串行”。
//此处不能用方法1(继承thread类),定义d1、d2对象,因为synchronized的参数this打在的是对象中(synchronized运行结束this上的标记自动消亡),  这种方法会使this标记打在了两个对象,而Runnable方法可使this打在一个对象,达到目的。
class Downloader implements Runnable{ static int i = 1;                //定义静态变量,可以使类中所有对象共用public void run() {  while(true){synchronized(this){if(i>10)  {   break; }try{  Thread.sleep(1000);  } catch(Exception ex){}  System.out.println("下载进度:"+i*10+"%");i++;}          }       }
}
class ThreadTest{public static void main (String[] args) throws Exception {Downloader d = new Downloader();new Thread(d).start();  new Thread(d).start();}
}
  • 实际过程中,解决同步问题的方法是:人为进行资源划分(如一个线程下载前50%,另一个线程下载后50%)。

ch7.JavaIO操作

IO:输入输出。

输入设备:键盘、鼠标、扫描仪

输出设备:打印机、显示器

同时属于输入输出设备:硬盘

输入设备和输出设备是站在内存的角度划分的。

将文件从硬盘上读入,QQ收到对方信息;将文件保存到硬盘,QQ输出信息给对方。

这里重点讲解文件输入输出,对应的包是java.io。

7.1 封装文件

java.io.File:文件封装,得到文件信息,删除文件,重命名文件

[例1]用File类封装E:/test.txt.

import java.io.*;
class IOTest{public static void main (String[] args) {File f = new File("E:/test.txt");f.delete();}
}

[例2]列出D盘下面所有的文件,并显示.

import java.io.*;
class IOTest{public static void main (String[] args) {File f = new File("D:/");File[] files = f.listFiles();for(File file : files){System.out.println(file.getPath() + ":" + file.length());}}
}

[例3]删除E:/testDir下面的所有文件.

import java.io.*;
class IOTest{public static void main (String[] args) {File f = new File("D:/testDir");File[] files = f.listFiles();for(File file : files){file.delete();}}
}

[例4]编写一个病毒,用户运行,自动清空输入文件夹路径中所有的文件和文件夹。

package VirusTest;
import java.io.File;
public class VirusTest {public static void FileDelete(File f) {if(f.isDirectory()){File[] files = f.listFiles();for (File file : files) {FileDelete(file);}}f.delete();}public static void main(String[] args) throws Exception{String str = javax.swing.JOptionPane.showInputDialog("请输入您要删除的文件夹");File f = new File(str);FileDelete(f);}
}

7.2 读文件

场景:test.txt里面有一些内容,读入到内存后,显示在屏幕上。

7.2.1 java.io.FileInputStream

FileInputStream类一个个字节读取,对中文支持不佳。文件输入输出流,打开之后,记得及时关闭

【注】字节流和字符流

字节流以字节的形式读取文件,对于有一些“双字节字符”,支持不好。为了解决该问题,Java中推出专门支持字符流的文件输入输出类。

import java.io.*;
class IOTest{public static void main (String[] args) throws Exception{File f = new File("test.txt");FileInputStream fis = new FileInputStream(f);while(true){int i = fis.read();if(i==-1) break;char ch = (char)i;System.out.print(ch);}fis.close();}
}

批量读取

import java.io.*;
class IOTest{public static void main (String[] args)  throws Exception{File f = new File("test.txt");FileInputStream fis = new FileInputStream(f);byte[] data = new byte[(int)f.length()];fis.read(data);String s = new String(data);System.out.println(s);       fis.close();}
}

7.2.2 java.io.FileReader

字符读取,可一个个字符读,也可一块块读,支持字符。

7.2.3 java.io.BufferedReader

重点针对字符特别是多字节字符讲解的不是FileReader,最常见使用的是“按行读”的另一个类:java.io.BufferedReader。如果对字符串进行读取,最佳办法是用:BufferedReader。它支持按行读字符串,和FileReader配套

import java.io.*;
class IOTest{public static void main (String[] args)  throws Exception{File f = new File("test.txt");FileReader fr = new FileReader(f);BufferedReader br = new BufferedReader(fr);while(true){String s = br.readLine();if(s==null) break;System.out.println(s);}fr.close();}
}

字节流读取(FileInputStream)和字符流读取(FileReader/BufferedReader)进行比较,FileInputStream(适合图像、视频、语音、文本都支持),而字符流读取一般只适合字符和字符串。

【总结】

  • java.io.FileInputStream:字节读取,可一个个字节读,也可一块块读,使用最广
  • java.io.FileReader:字符读取,可一个个字符读,也可一块块读,支持字符
  • java.io.BufferedReader:支持按行读字符串,和FileReader配套

7.3 写文件

场景:定义一个变量,保存到test.txt中。

  • java.io.FileOutputStream:字节流输出

注意:向文件保存数据时,有两种模式:1)在文件末尾添加; 2)覆盖原有内容,用append参数确定。

import java.io.*;
class IOTest{public static void main (String[] args)  throws Exception{File f = new File("test.txt");FileOutputStream fos = new FileOutputStream(f, false); //append参数为false,覆盖原有内容String str = "CSU中南大学";fos.write(str.getBytes()); //getBytes函数转为字节数组,然后写入文件fos.close();}
}
  • java.io.FileWriter:字符流输出
  • java.io.PrintStream:支持丰富的格式对字符串进行输出,字符串万能输出,和FileOutputStream配套

[例1]将一个99乘法表保存到test.txt中。

import java.io.*;
class IOTest{public static void main (String[] args) throws Exception{File f = new File("test.txt");FileOutputStream fos = new FileOutputStream(f, false);PrintStream ps = new PrintStream(fos);for(int i=1;i<=9;i++){for(int j=1;j<=i;j++){ps.print(i + "*" + j + "=" + i*j + " ");}ps.println();}      fos.close();}
}

[例2]将一个图像加密,加密方法:每个字节的值+3。

import java.io.*;
class IOTest{public static void main (String[] args)  throws Exception{File f1 = new File("img1.jpg");File f2 = new File("img2.jpg");FileInputStream fis = new FileInputStream(f1);FileOutputStream fos = new FileOutputStream(f2);     while(true){int i = fis.read();if(i==-1) break;i+=3;fos.write(i);}fos.close();fis.close();}
}

另外,RandomAccessFile类可以提供文件的随机访问,既支持文件读,又支持文件写。

ch8.Java界面开发与事件处理

本章讲述Java开发桌面应用程序,包括用Swing开发GUI程序、Java事件处理与Java绘图。

Swing:Java中的一个包,负责开发GUI程序

GUI:图形用户界面,一般指可视化桌面系统中的应用程序。

Windows:将应用程序从字符界面拓展到图形界面。

常见图形用户界面的基本结构

  • 界面(容器窗口)

  • 控件(界面上的组件,如按钮、文本框等)

  • 渲染(颜色、字体等)

  • 事件响应(完成功能)

界面控件、渲染中的图标使用的包:javax.swing包【注:javax的x:eXtension(扩展)】

渲染(颜色:Color、字体:Font)使用的包:java.awt包。

8.1 界面

又称容器、窗口,提供整个界面的空间。

  • 框架界面: javax.swing.JFrame
  • 窗口界面: javax.swing.JWindow
  • 对话框界面: javax.swing.JDialog

一般掌握第(1)种即可。

显示:setVisible函数

[例]在桌面出现一个界面,标题是:HelloWorld

用框架界面

import javax.swing.JFrame;
class GUI1{public static void main(String[] args) throws Exception  {JFrame jfm = new JFrame("HelloWorld");jfm.setSize(600,400);jfm.setLocation(300,200);jfm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);     //退出框架界面jfm.setVisible(true);}
}

通过构造函数进行初始化

import javax.swing.JFrame;
class GUI extends JFrame{public GUI(){super("HelloWorld");        //调用父类的构造函数this.setSize(600,400);this.setLocation(300,200);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args) throws Exception  {new GUI();}
}

8.2 控件

界面上的组件,如按钮、文本框、复选框等。

注意:Java中,容器还有:面板 javax.swing.JPanel

一般我们在界面上添加一个面板,面板上增加控件

  • 按钮:javax.swing.JButton
  • 静态文本:javax.swing.JLabel
  • 文本框:javax.swing.JTextField
  • 密码框:javax.swing.JPasswordField
  • 多行文本框:javax.swing.JTextArea
  • 下拉菜单:javax.swing.JComboBox
  • 复选框:javax.swing.JCheckBox

举一反三:

  • 知道一个控件,用哪个类?
  • 查文档看构造函数和其他重要函数
  • 将控件实例化后加到容器中
import javax.swing.*;
class GUI extends JFrame{private JLabel jlb = new JLabel("——————欢迎来到中南大学社团学生注册系统——————");    private JButton jbt = new JButton("学生注册");private JLabel jlbAcc = new JLabel("请您输入账号");private JTextField jtfAcc = new JTextField(20);private JLabel jlbAdd = new JLabel("请您选择您的家乡");private JComboBox jcbAdd = new JComboBox(); private JCheckBox jcbMember = new JCheckBox("是否立即成为会员",true);    private JLabel jlbInfo = new JLabel("请您输入个人详细描述");private JTextArea jtaInfo = new JTextArea(20,30);private JPanel  jpl = new JPanel();public GUI(){jpl.add(jlb);       jpl.add(jbt);   jpl.add(jlbAcc);  jpl.add(jtfAcc);jpl.add(jlbAdd);  jpl.add(jcbAdd);  jpl.add(jlbInfo);  jpl.add(jtaInfo);jcbAdd.addItem("湖南");   jcbAdd.addItem("湖北");jcbAdd.addItem("河南");  jcbAdd.addItem("河北");jpl.add(jcbMember);this.add(jpl);        this.setSize(400,600);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args) throws Exception  {new GUI();}
}

8.3 渲染

  • 包含颜色、字体(java.awt)、图标(javax.swing)三部分

  • 任何界面和控件都可以设置背景颜色和前景颜色

    setBackground(颜色) setForeground(颜色) (文档可查)

​ 凡是有字的控件,都有setFont函数(文档可查)

  • 颜色:java.awt.Color

  • 字体:java.awt.Font

    import javax.swing.*;
    import java.awt.*;
    class GUI extends JFrame{private JButton jbt = new JButton("学生注册");private JPanel  jpl = new JPanel();public GUI(){jpl.setBackground(new Color(0,255,255));jbt.setBackground(Color.blue);jbt.setForeground(Color.yellow);Font f = new Font("微软雅黑",Font.BOLD,50);jbt.setFont(f);jpl.add(jbt);this.add(jpl);       this.setSize(400,600);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );this.setVisible(true);}public static void main(String[] args) throws Exception  {new GUI();}
    }
    
  • 图标:很多控件都可以设置图标,如按钮、静态文本等。但不是所有,比如文本框就不能。具体看文档。用的函数:setIcon函数

    注意:Icon和ImageIcon在swing中

    主要方法有:

    控件.setBackground和setForeground(颜色)

    控件.setFont(字体)

    控件.setIcon(图标)

    【例】将按钮设置为图标形式。

    import javax.swing.*;
    import java.awt.*;
    class GUI extends JFrame{private JButton jbt = new JButton();private JPanel  jpl = new JPanel();public GUI(){ImageIcon icon = new ImageIcon("img.jpg");jbt.setIcon(icon);jbt.setText("这是一个按钮");jpl.add(jbt);this.add(jpl);       this.setSize(600,800);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );this.setVisible(true);}public static void main(String[] args) throws Exception  {new GUI();}
    }
    

8.4 界面布局管理

布局:将控件有序的放在界面上,使用java.awt包。

8.4.1 FlowLayout

JPanel默认的布局方式是:流式布局(FlowLayout),优先放在1行,放不下,到后面1行。该布局方式由java.awt.FlowLayout来管理;
任何容器管理类都有setLayout函数设置布局。

[例]将一个按钮,一个文本框放在界面上。

import javax.swing.*;
import java.awt.*;
class Layout1 extends JFrame{private JTextField jtf = new JTextField(20);private JButton jbt = new JButton("按钮");private JPanel jpl = new JPanel();    public Layout1(){FlowLayout fl = new FlowLayout(FlowLayout.LEFT,20,20);jpl.setLayout(fl);this.add(jpl);    jpl.add(jtf);       jpl.add(jbt);this.setSize(300,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args) throws Exception  {new Layout1();}
}

8.4.2 GridLayout

网格布局,将界面设置为多行多列的格子,放置控件。该布局方式由java.awt.GridLayout来管理。

[例1]放置24个按钮在界面上。

import javax.swing.*;
import java.awt.*;
class Layout1 extends JFrame{private JPanel jpl = new JPanel();    public Layout1(){GridLayout gl = new GridLayout(6,4); jpl.setLayout(gl);this.add(jpl); for(int i=1;i<=24;i++){jpl.add(new JButton(String.valueOf(i)));}             this.setSize(300,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args) throws Exception  {new Layout1();}
}

[例2]制作一个8*8国际象棋棋盘。

import javax.swing.*;
import java.awt.*;
class Layout1 extends JFrame{private JPanel jpl = new JPanel();    public Layout1(){GridLayout gl = new GridLayout(8,8); jpl.setLayout(gl);this.add(jpl); for(int i=1;i<=8;i++){for(int j=1;j<=8;j++){JPanel pl = new JPanel();if((i+j)%2==0)  {pl.setBackground(Color.white);}else { pl.setBackground(Color.black);}jpl.add(pl);}}             this.setSize(300,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args) throws Exception  {new Layout1();}
}

8.4.3 BorderLayout

边界布局:将界面分为东西南北中,添加控件。该布局方式由java.awt.BorderLayout来管理。

JFrame的默认布局方式是BorderLayout。

import javax.swing.*;
import java.awt.*;
class Layout1 extends JFrame{private JPanel jpl = new JPanel();    public Layout1(){BorderLayout bl = new BorderLayout(); jpl.setLayout(bl);this.add(jpl);    jpl.add(new JButton("按钮"),BorderLayout.SOUTH);jpl.add(new JTextField(),BorderLayout.NORTH);jpl.add(new JTextArea(),BorderLayout.CENTER);jpl.add(new JButton("按钮"),BorderLayout.WEST);jpl.add(new JButton("按钮"),BorderLayout.EAST);this.setSize(300,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args) throws Exception  {new Layout1();}
}

[注]教科书中有关于计算器的编制程序。

8.4.4 完全自由布局

在完全自由布局中,控件的位置,大小,用坐标决定,而不是由界面大小决定。实际上是:设置容器布局为null,然后通过setSize设置大小,setLocation设置位置。

部分情况不适用该布局方式的原因:坐标体系在不同的操作系统不能保证相同

[例1]设置一个按钮,从界面上方以抛物线的形式掉下来。

import javax.swing.*;
import java.awt.*;
class Layout1 extends JFrame implements Runnable{private JButton jbt = new JButton();int X,Y = 0;public Layout1(){jbt.setIcon(new ImageIcon("img.jpg"));this.setLayout(null);  jbt.setSize(80,60);      this.add(jbt);      this.setSize(300,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);Thread th = new Thread(this);th.start();}public void run(){while(true){try{Thread.sleep(20)  ;} catch(Exception e){}X++;  Y=X*X/100;jbt.setLocation(X,Y);}}public static void main(String[] args) throws Exception  {new Layout1();}
}

[例2]小球自由落体掉下,弹起来,再次自由落体。

import javax.swing.*;
import java.awt.*;
class Layout1 extends JFrame implements Runnable{private JButton jbt = new JButton();int Y = 0;int DIR = 1;public Layout1(){Icon icon = new ImageIcon("img.jpg");jbt.setIcon(icon);this.setLayout(null);  jbt.setSize(icon.getIconWidth(),icon.getIconHeight());      this.add(jbt);      this.setSize(300,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);Thread th = new Thread(this);th.start();}public void run(){while(true){try{Thread.sleep(20);} catch(Exception e){}if(DIR==1)  { Y+=2;     if(Y>=(this.getHeight()-jbt.getHeight())) DIR=0; }else if(DIR==0)  { Y--;     if(Y<=0) DIR=1; }jbt.setLocation(60,Y);}}public static void main(String[] args) throws Exception {new Layout1();}
}

8.5 事件监听机制

Java事件处理在java.awt.event包中。

事件:程序对某些操作的响应。

点击按钮,打印“Hello”的三个步骤是:(其余都类似)

  • 事件响应类必须能够听到相应的命令(加一个耳朵)
    点击按钮如果要响应,必须让响应类实现java.awt.event.ActionListener接口
  • 将事件响应的代码,放在接口中重写的函数
  • 绑定,确保按钮发出命令,响应对象能够执行

①实现接口(监听器)、②编写函数、③绑定,叫做事件监听机制

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Printer implements ActionListener{            //①实现接口public void actionPerformed(ActionEvent e){     //②事件响应代码System.out.println("Hello");}
}class EventTest extends JFrame{private JButton jbt = new JButton("按钮");public EventTest(){Printer p = new Printer();   jbt.addActionListener(p);                   //③绑定,确保按钮发出命令,p能够执行this.add(jbt,BorderLayout.NORTH);this.setSize(300,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args)    {new EventTest();}
}

更加简洁的方法是:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class EventTest extends JFrame implements ActionListener{private JButton jbt = new JButton("按钮");public EventTest(){jbt.addActionListener(this); this.add(jbt,BorderLayout.NORTH);this.setSize(300,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public void actionPerformed(ActionEvent e){     System.out.println("Hello");}public static void main(String[] args){new EventTest();}
}

Java中定义,不同的事件,由不同的XXXListener来监听。

事件响应函数中,ActionEvent参数表示命令发出时,封装的命令发出方的信息

[例]实现两个按钮,一个按钮点击,界面变红,另一个点击,界面变蓝。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;class EventTest extends JFrame implements ActionListener{private JButton jbt1 = new JButton("变红");   private JButton jbt2 = new JButton("变蓝");private JPanel jpl = new JPanel();public EventTest(){this.add(jbt1,BorderLayout.NORTH);this.add(jbt2,BorderLayout.SOUTH);      this.add(jpl,BorderLayout.CENTER);      jbt1.addActionListener(this); jbt2.addActionListener(this); this.setSize(300,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public void actionPerformed(ActionEvent e){     if(e.getSource()==jbt1){        //getSource()函数可以得知事件的源头jpl.setBackground(Color.red);}else{jpl.setBackground(Color.blue);           }}public static void main(String[] args)    {new EventTest();}
}

8.6 常见监听事件处理

下列Listener,分别监听以下事件:

  • ActionListener:监听按钮点击,文本框内回车,菜单单击、其他支持单击响应的控件,以及一些拥有addActionListener函数的控件

  • ItemListener:监听选项变化时要响应的事件,如下拉菜单等

    下拉菜单中有红绿蓝三个选项,选择时,界面自动变色

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class EventTest extends JFrame implements ItemListener {private JComboBox jcb = new JComboBox();   private JPanel jpl = new JPanel();public void itemStateChanged(ItemEvent e){if(jcb.getSelectedItem().equals("红")){jpl.setBackground(Color.red);}else if(jcb.getSelectedItem().equals("绿")){jpl.setBackground(Color.green);         }else{jpl.setBackground(Color.blue);            }}public EventTest(){this.add(jcb,BorderLayout.NORTH);  this.add(jpl,BorderLayout.CENTER);          jcb.addItemListener(this);  jcb.addItem("红");         jcb.addItem("绿");     jcb.addItem("蓝");     this.setSize(300,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args)    {new EventTest();}
}
  • MouseListener:监听鼠标操作(单击,双击,进入,离开等)

[例1]鼠标进入按钮,按钮变红,退出,按钮变白。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;class EventTest extends JFrame implements MouseListener{private JButton jbt = new JButton("按钮");public EventTest(){jbt.addMouseListener(this); this.add(jbt,BorderLayout.NORTH);this.setSize(300,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public void mouseClicked(MouseEvent e) {}public void mouseEntered(MouseEvent e) {jbt.setBackground(Color.red);}public void mouseExited(MouseEvent e) {jbt.setBackground(Color.white);}public void mousePressed(MouseEvent e) {}public void mouseReleased(MouseEvent e) {}public static void main(String[] args)    {new EventTest();}
}

[例2]界面上有一个图片,鼠标进入,图片随机躲开。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;class EventTest extends JFrame implements MouseListener{private JLabel jlb = new JLabel();int X=50,Y=50;public EventTest(){Icon icon = new ImageIcon("img.jpg");jlb.setIcon(icon);this.setLayout(null);       this.add(jlb);jlb.setSize(icon.getIconWidth(),icon.getIconHeight());jlb.setLocation(X,Y);jlb.addMouseListener(this); this.setSize(400,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public void mouseClicked(MouseEvent e) {}public void mouseEntered(MouseEvent e) {X = (int)(Math.random()*this.getWidth())-jlb.getWidth();Y = (int)(Math.random()*this.getHeight())-jlb.getHeight();jlb.setLocation(X,Y);}public void mouseExited(MouseEvent e) {}public void mousePressed(MouseEvent e) {}public void mouseReleased(MouseEvent e) {}public static void main(String[] args)    {new EventTest();}
}
  • MouseMotionListener:监听鼠标移动和拖动操作

[例]鼠标在界面上移动,标题栏显示鼠标的当前坐标。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;class EventTest extends JFrame implements MouseMotionListener{public EventTest(){this.addMouseMotionListener(this);this.setSize(400,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public void mouseDragged(MouseEvent e) {String str = e.getX() + "," + e.getY();this.setTitle(str);}public void mouseMoved(MouseEvent e)  {}public static void main(String[] args)    {new EventTest();}
}

作业:界面上有一个图片,鼠标可以将图片从一个地方拖动到另一个地方。

作业:界面上有10个图片,鼠标可以将某个图片从一个地方拖动到另一个地方。

  • KeyListener:监听键盘输入时要响应的事件(如俄罗斯方块)

[例]使用键盘上的上下左右键,能控制界面上一个图片的上下左右移动。

[注意]键盘事件一般被更大的容器先截获

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;class EventTest extends JFrame implements KeyListener{private JLabel jlb = new JLabel();int X=50,Y=50;public EventTest(){Icon icon = new ImageIcon("img.jpg");jlb.setIcon(icon);this.setLayout(null);     this.add(jlb);jlb.setSize(icon.getIconWidth(),icon.getIconHeight());jlb.setLocation(X,Y);this.addKeyListener(this);     //键盘事件应通过界面截获this.setSize(400,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);} public void keyPressed(KeyEvent e) {int keyCode = e.getKeyCode();if(keyCode==KeyEvent.VK_UP){Y-=30;}else if(keyCode==KeyEvent.VK_DOWN){Y+=30;}else if(keyCode==KeyEvent.VK_LEFT){X-=30;}else if(keyCode==KeyEvent.VK_RIGHT){X+=30;}jlb.setLocation(X,Y);} public void keyReleased(KeyEvent e) {} public void keyTyped(KeyEvent e)  {}    public static void main(String[] args)    {new EventTest();}
}

[综合例题]界面中一个图片掉下,鼠标进入,暂停,离开,继续掉。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;class EventTest extends JFrame implements Runnable,MouseListener {private JLabel jlb = new JLabel();int X=50,Y=50;boolean RUN = true;public EventTest(){Icon icon = new ImageIcon("img.jpg");jlb.setIcon(icon);this.setLayout(null);     this.add(jlb);jlb.setSize(icon.getIconWidth(),icon.getIconHeight());jlb.setLocation(X,Y);this.addMouseListener(this);this.setSize(400,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);new Thread(this).start();}    public void mouseClicked(MouseEvent e) {}public void mouseEntered(MouseEvent e) {RUN = false;}public void mouseExited(MouseEvent e) {RUN = true;new Thread(this).start();}public void mousePressed(MouseEvent e) {}public void mouseReleased(MouseEvent e) {} public void run(){while(RUN){try{ Thread.sleep(100); }catch(Exception e){}Y+=20;      jlb.setLocation(X,Y);}}public static void main(String[] args)    {new EventTest();}
}
  • AdjustmentListener:监听一些具有调整功能的控件(如滚动条)

  • FocusListener:监听当控件获得或者失去焦点时要响应的事件

​ 如焦点到一行时上面的提示信息消失,移除后提示信息继续存在。

8.7 Java绘图

8.7.1 绘制基本图形

用控件组成的界面,一般叫做高级界面;纯粹用绘画方式组成的界面,一般叫做低级界面。

低级界面开发的原理:以面板为画布,画布上画内容,将画布放在JFrame上,画布单独编写一个类

预备知识:

  • 画布上画内容,将该工作重写在从父类继承过来的paint函数中
  • paint函数会自动调用;如果手工调用,只能用repaint函数
  • 具体画图,采用paint函数中的Graphics参数(相当于画笔

注意:Graphics有一个子类Graphics2D,画笔可以直接转换成该类型,Graphics2D内拥有更加丰富的画笔功能

基础演示:

import javax.swing.*;
import java.awt.*;
class MyCanvas extends JPanel{public void paint(Graphics g){Graphics2D g2d = (Graphics2D)g;g2d.setStroke(new BasicStroke(50));     //设置粗细g2d.setColor(Color.red);g2d.drawLine(0,0,100,100);}
}class Paint1 extends JFrame{private MyCanvas mc = new MyCanvas();public Paint1(){this.add(mc);this.setSize(800,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args)    {new Paint1();}
}

[例1]界面上,不断随机位置出现随机颜色的线段。

import javax.swing.*;
import java.awt.*;
class MyCanvas extends JPanel implements Runnable{public MyCanvas(){new Thread(this).start();}public void paint(Graphics g){Graphics2D g2d = (Graphics2D)g;g2d.setStroke(new BasicStroke((int)(Math.random()*50)));g2d.setColor(new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256)));g2d.drawLine((int)(Math.random()*this.getWidth()),(int)(Math.random()*this.getHeight()),(int)(Math.random()*this.getWidth()),(int)(Math.random()*this.getHeight()));}public void run(){while(true){try{ Thread.sleep(50);   } catch(Exception e){}repaint();}}
}class Paint1 extends JFrame{private MyCanvas mc = new MyCanvas();public Paint1(){this.add(mc);this.setSize(800,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args)    {new Paint1();}
}

[例2]界面上,鼠标拖动,可以连续画线。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class MyCanvas extends JPanel implements MouseMotionListener{int X=0,Y=0;public MyCanvas(){this.addMouseMotionListener(this);}public void mouseDragged(MouseEvent e) {X = e.getX();  Y = e.getY();this.repaint();}public void mouseMoved(MouseEvent e)  {}      public void paint(Graphics g){Graphics2D g2d = (Graphics2D)g;g2d.setColor(Color.green);g2d.fillOval(X,Y,20,20); //参数(int x,int y,int width,int height)函数用当前颜色填充由指定矩形界定的椭圆}
}class Paint1 extends JFrame{private MyCanvas mc = new MyCanvas();public Paint1(){this.add(mc);this.setSize(800,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args)    {new Paint1();}
}

8.7.2 绘制图像

绘制图像,使用的是画笔的drawImage函数。

  • 原图绘制:drawImage(Image img,int x,int y, ImageObserver observer)
  • 原图缩放绘制:drawImage(Image img,int x,int y,int width,int height, ImageObserver observer)

基础演示:

import javax.swing.*;
import java.awt.*;
class MyCanvas extends JPanel{private   Image img = Toolkit.getDefaultToolkit().createImage("img.jpg");public void paint(Graphics g){Graphics2D g2d = (Graphics2D)g;g2d.drawImage(img,50,60,this);g2d.drawImage(img,200,300,200,50,this);}
}class Paint1 extends JFrame{private MyCanvas mc = new MyCanvas();public Paint1(){this.add(mc);this.setSize(800,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args)    {new Paint1();}
}

[例]一个图像,在界面上渐渐放大。

import javax.swing.*;
import java.awt.*;
class MyCanvas extends JPanel implements Runnable{private   Image img = Toolkit.getDefaultToolkit().createImage("img.jpg");int X=0,Y=0;public MyCanvas(){   new Thread(this).start(); }public void run(){while(true){try{  Thread.sleep(50); } catch(Exception ex){}X+=10; Y+=10;repaint();}}public void paint(Graphics g){Graphics2D g2d = (Graphics2D)g;g2d.drawImage(img,20,20,X,Y,this);}
}class Paint1 extends JFrame{private MyCanvas mc = new MyCanvas();public Paint1(){this.add(mc);this.setSize(800,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args)    {new Paint1();}
}
  • 截取图像部分绘制:drawImage(Image img,
    int dx1,int dy1,int dx2,int dy2, //d指destination
    int sx1,int sy1,int sx2,int sy2, //s指source
    ImageObserver observer)

[例]将原图的左边一半,右边一半,上面一半,下面一半分别绘制。

import javax.swing.*;
import java.awt.*;
class MyCanvas extends JPanel{private   Image img = Toolkit.getDefaultToolkit().createImage("img.jpg");public void paint(Graphics g){Graphics2D g2d = (Graphics2D)g;g2d.drawImage(img,0,0,100,100,0,0,img.getWidth(this)/2,img.getHeight(this), this);g2d.drawImage(img,200,200,300,300,img.getWidth(this)/2,0,img.getWidth(this),img.getHeight(this), this);                g2d.drawImage(img,300,50,400,100,0,0,img.getWidth(this),img.getHeight(this)/2, this); g2d.drawImage(img,400,200,500,300,0,img.getHeight(this)/2,img.getWidth(this),img.getHeight(this),this);                  }
}class Paint1 extends JFrame{private MyCanvas mc = new MyCanvas();public Paint1(){this.add(mc);this.setSize(800,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args)    {new Paint1();}
}

8.7.3 图像旋转

利用rotate函数。 rotate(double theta,double x,double y)

  • theta - 以弧度表示的旋转角度(顺时针)
  • x - 旋转原点的x坐标
  • y - 旋转原点的y坐标
import javax.swing.*;
import java.awt.*;
class MyCanvas extends JPanel{private   Image img = Toolkit.getDefaultToolkit().createImage("img.jpg");public void paint(Graphics g){Graphics2D g2d = (Graphics2D)g;g2d.drawImage(img,200,300,this);g2d.rotate(Math.PI/2,200+img.getWidth(this)/2,300+img.getHeight(this)/2);g2d.drawImage(img,200,300,this);}
}class Paint1 extends JFrame{private MyCanvas mc = new MyCanvas();public Paint1(){this.add(mc);this.setSize(800,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args)    {new Paint1();}
}

[例]图像边移动边旋转。

import javax.swing.*;
import java.awt.*;
class MyCanvas extends JPanel implements Runnable{private   Image img = Toolkit.getDefaultToolkit().createImage("img.jpg");double r = 0;int X=0;public MyCanvas(){  new Thread(this).start(); }public void run(){while(true){try{ Thread.sleep(50);    } catch(Exception e){}r = r + 0.1;X+=10;repaint();}}public void paint(Graphics g){Graphics2D g2d = (Graphics2D)g;g2d.setColor(Color.white);g2d.fillRect(0,0,this.getWidth(),this.getHeight());     //实现之前经过的图像不在界面上显示g2d.rotate(r,0+X+img.getWidth(this)/2,0+X+img.getHeight(this)/2);g2d.drawImage(img,0+X,0+X,this);}
}class Paint1 extends JFrame{private MyCanvas mc = new MyCanvas();public Paint1(){this.add(mc);this.setSize(800,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args)    {new Paint1();}
}

ch9.Java网络编程

9.1 网络基础知识

网络中有两个重要的协议,分别是:

  • TCP:传输控制协议 面向连接 打电话

  • UDP:数据包协议 面向数据包 发短信

使用较多的是TCP。

网络应用程序有微信、QQ、抖音、浏览器等,Java网络编程讲解的是这些网络应用程序最底层的内容。

有两种服务器和客户端的通信模式:

  • C/S模式:客户端/服务器 客户安装应用程序,和服务器通信 微信、QQ

  • B/S模式:浏览器/服务器 客户端安装浏览器,和服务器通信 www.csu.edu.cn在浏览器中运行

信息通过客户端和服务器通信,客户端之间的通信,靠服务器转发;故网络应用程序,一定要分为客户端和服务器程序。

网络上的计算机靠IP地址来定位,出现在客户端

用端口号(port)确定不同的网络应用程序类型,由服务器决定

端口号用数字表示,一般0-65535之间,有些非常常见的应用程序,已经预设了端口号:HTTP(浏览器:80),FTP(21)等等。一般应用程序,建议使用4位数端口号,以免冲突

9.2 单个客户端连接服务器

场景:客户端给服务器发送一句:你好,服务器回应,欢迎。

客户端连接服务器的步骤如下:[使用java.net包]

  • 1:服务器先运行,确定端口号
  • 2:客户端通过服务器IP地址+端口号,连上
  • 3:通信

运用到的类如下:

  • ServerSocket:启动服务器;接受客户端连接
  • Socket: 客户端连上服务器,双方通信

Server1.java:

import java.net.*;
import java.io.*;
class Server1 {public static void main(String[] args) throws Exception   {ServerSocket ss = new ServerSocket(9999);Socket s = ss.accept(); InputStreamReader isr = new InputStreamReader(s.getInputStream());BufferedReader br = new BufferedReader(isr);String msg = br.readLine();System.out.println(msg);PrintStream ps = new PrintStream(s.getOutputStream());ps.println("欢迎你连上服务器!");}
}

Client1.java:

import java.net.*;
import java.io.*;
class Client1 {public static void main(String[] args) throws Exception   {Socket s = new Socket("172.17.10.147", 9999);PrintStream ps = new PrintStream(s.getOutputStream());ps.println("你好,我是客户端");BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));String str = br.readLine();System.out.println(str);}
}

[例1]客户端和服务器互相聊天:

客户端和服务器都有文本框,输入内容,回车(ActionListener),信息发给对方显示;反过来也支持。

Server2.java:

import java.net.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Server extends JFrame implements ActionListener,Runnable{private JTextField jtf = new JTextField();private JTextArea jta = new JTextArea();private BufferedReader br = null;private PrintStream ps = null;public Server() throws Exception{this.setTitle("服务器");this.add(jtf,BorderLayout.SOUTH);this.add(jta,BorderLayout.CENTER);jtf.addActionListener(this);this.setSize(300,500);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);ServerSocket ss = new ServerSocket(9999);Socket s = ss.accept(); br = new BufferedReader(new InputStreamReader(s.getInputStream()));ps = new PrintStream(s.getOutputStream());new Thread(this).start();}public void run() {while(true){try{ String msg = br.readLine();jta.append(msg + "\n");}catch(Exception e){}}}public void actionPerformed(ActionEvent e){jta.append(jtf.getText() + "\n");ps.println("服务器说:" + jtf.getText());}public static void main(String[] args) throws Exception   {new Server();    }
}

Client2.java:

import java.net.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Client extends JFrame implements ActionListener,Runnable{private JTextField jtf = new JTextField();private JTextArea jta = new JTextArea();private BufferedReader br = null;private PrintStream ps = null;public Client() throws Exception{this.setTitle("客户端");this.add(jtf,BorderLayout.NORTH);this.add(jta,BorderLayout.CENTER);jtf.addActionListener(this);this.setSize(300,500);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);Socket s = new Socket("172.17.10.147",9999); br = new BufferedReader(new InputStreamReader(s.getInputStream()));ps = new PrintStream(s.getOutputStream());new Thread(this).start();}public void run() {while(true){try{    String msg = br.readLine();jta.append(msg + "\n");}catch(Exception e){}}}public void actionPerformed(ActionEvent e){jta.append(jtf.getText() + "\n");ps.println("客户端说:" + jtf.getText());}public static void main(String[] args) throws Exception   {new Client();}
}

[例2·B/S典型例子]客户端给服务器发信息,如果发N字母,服务器发给客户端一个随机数字;如果发M字母,服务器给客户端发送一个欢迎文本。

Server3.java:

import java.net.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Server extends JFrame implements Runnable{private BufferedReader br = null;private PrintStream ps = null;public Server() throws Exception{this.setTitle("服务器");this.setSize(200,200);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);ServerSocket ss = new ServerSocket(9999);Socket s = ss.accept(); br = new BufferedReader(new InputStreamReader(s.getInputStream()));ps = new PrintStream(s.getOutputStream());new Thread(this).start();}public void run() {while(true){try{   String msg = br.readLine();if(msg.equals("N")){  ps.println("数字:" + Math.random()); }if(msg.equals("M")){  ps.println("文本:欢迎"); }}catch(Exception e){}}}public static void main(String[] args) throws Exception   {new Server();  }
}

Client3.java:

import java.net.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Client extends JFrame implements ActionListener,Runnable{private JTextField jtf = new JTextField();private JTextArea jta = new JTextArea();private BufferedReader br = null;private PrintStream ps = null;public Client() throws Exception{this.setTitle("客户端");this.add(jtf,BorderLayout.NORTH);this.add(jta,BorderLayout.CENTER);jtf.addActionListener(this);this.setSize(300,500);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);Socket s = new Socket("172.17.10.147",9999); br = new BufferedReader(new InputStreamReader(s.getInputStream()));ps = new PrintStream(s.getOutputStream());new Thread(this).start();}public void run() {while(true){try{    String msg = br.readLine();jta.append(msg + "\n");}catch(Exception e){}}}public void actionPerformed(ActionEvent e){ps.println(jtf.getText());}public static void main(String[] args) throws Exception{new Client();}
}

9.3 多个客户端连接服务器

应用场合:多个客户端连上服务器,客户端之间的通信依靠服务器转发。

9.3.1 服务器端群聊案例

[例1]多个客户端连上服务器:服务器端有一个界面,界面上有一个多行文本框,多个客户端连接,连上就在服务器显示“有人连上” 。

Server1.java:

import java.net.*;
import java.io.*;
import javax.swing.*;
class Server extends JFrame implements Runnable{private JTextArea jta = new JTextArea();private ServerSocket ss = null;public Server() throws Exception{this.add(jta);this.setSize(200,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);ss = new ServerSocket(9999);      new Thread(this).start();}public void run(){while(true){try{Socket s = ss.accept();jta.append("有人连上!!\n");}catch(Exception ex){}}}public static void main(String[] args) throws Exception   {new Server();}
}

Client1.java:

import java.net.*;
import java.io.*;
class Client {public static void main(String[] args) throws Exception   {Socket s = new Socket("172.17.10.148", 9999);       }
}

[例2]服务器端群聊:每个客户端都可以输入信息,回车发送,发送之后的信息,在服务器端显示。

类中类,多线程,每个客户端连接对应一个线程。

Server2.java:

import java.net.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
class Server  extends JFrame implements Runnable{private JTextArea jta = new JTextArea();private ServerSocket ss = null;public Server() throws Exception{this.add(jta);       jta.setFont(new Font("宋体",Font.BOLD,30));this.setSize(200,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);ss = new ServerSocket(9999);       new Thread(this).start();}public void run(){while(true){try{Socket s = ss.accept();ChatThread ct = new ChatThread(s);     ct.start();}catch(Exception ex){}}}class ChatThread extends Thread{BufferedReader br = null;ChatThread(Socket s) throws Exception{br = new BufferedReader(new InputStreamReader(s.getInputStream()));}public void run(){while(true){try{String msg = br.readLine();jta.append(msg + "\n");}catch(Exception e){}}}}public static void main(String[] args) throws Exception   {new Server();}
}

Client2.java:

import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Client  extends JFrame implements ActionListener {private JTextField jtf = new JTextField();private PrintStream ps = null;private String nickName = null;public Client() throws Exception{this.add(jtf,BorderLayout.SOUTH);jtf.addActionListener(this);jtf.setFont(new Font("宋体",Font.BOLD,30));this.setSize(300,200);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);nickName = JOptionPane.showInputDialog("请您输入昵称");Socket s = new Socket("172.17.10.148", 9999);ps = new PrintStream(s.getOutputStream());}public void actionPerformed(ActionEvent e){ps.println(nickName + "说:" + jtf.getText());}public static void main(String[] args) throws Exception   {new Client();}
}

9.3.2 客户端群聊案例

[例3]客户端群聊:每个客户端都可以输入信息,回车发送,发送之后的信息,在每个客户端显示[服务器转发]。

Server3.java:

import java.net.*;
import java.io.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
class Server  extends JFrame implements Runnable{private ServerSocket ss = null;private ArrayList<ChatThread> users = new ArrayList<ChatThread>();    //一维变长数组,存放ChatThread类型变量public Server() throws Exception{this.setSize(200,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);ss = new ServerSocket(9999);        new Thread(this).start();}public void run(){while(true){try{Socket s = ss.accept();ChatThread ct = new ChatThread(s);     users.add(ct);              ct.start();}catch(Exception ex){}}}class ChatThread extends Thread{BufferedReader br = null;PrintStream ps = null;ChatThread(Socket s) throws Exception{br = new BufferedReader(new InputStreamReader(s.getInputStream()));ps = new PrintStream(s.getOutputStream());}public void run(){while(true){try{String msg = br.readLine();for(ChatThread ct : users){ct.ps.println(msg);}}catch(Exception e){}}}} public static void main(String[] args) throws Exception   {new Server();}
}

Client3.java:

import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Client  extends JFrame implements ActionListener,Runnable {private JTextField jtf = new JTextField();private JTextArea jta = new JTextArea();private PrintStream ps = null;private BufferedReader br = null;private String nickName = null;public Client() throws Exception{this.add(jta,BorderLayout.CENTER);this.add(jtf,BorderLayout.SOUTH);jtf.addActionListener(this);jtf.setFont(new Font("宋体",Font.BOLD,30));jta.setFont(new Font("宋体",Font.BOLD,30));this.setSize(400,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);nickName = JOptionPane.showInputDialog("请您输入昵称");Socket s = new Socket("172.17.10.148", 9999);ps = new PrintStream(s.getOutputStream());br = new BufferedReader(new InputStreamReader(s.getInputStream()));new Thread(this).start();}public void run(){while(true){try{String msg = br.readLine();jta.append(msg + "\n");}catch(Exception e){}}        }public void actionPerformed(ActionEvent e){ps.println(nickName + "说:" + jtf.getText());}public static void main(String[] args) throws Exception   {new Client();}
}

[例4]客户端群聊:每个客户端增加一个按钮,点击按钮,该客户端下线。其他客户端显示该客户端下线的消息。

Server4.java:

import java.net.*;
import java.io.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
class Server  extends JFrame implements Runnable{private ServerSocket ss = null;private ArrayList<ChatThread> users = new ArrayList<ChatThread>();public Server() throws Exception{this.setSize(200,400);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);ss = new ServerSocket(9999);     new Thread(this).start();}public void run(){while(true){try{Socket s = ss.accept();ChatThread ct = new ChatThread(s);     users.add(ct);              ct.start();}catch(Exception ex){}}}class ChatThread extends Thread{BufferedReader br = null;PrintStream ps = null;String nickName = null;ChatThread(Socket s) throws Exception{br = new BufferedReader(new InputStreamReader(s.getInputStream()));ps = new PrintStream(s.getOutputStream());}public void run(){while(true){try{String msg = br.readLine();String[] strs = msg.split(":"); if(strs[0].equals("NICK")){nickName = strs[1];}else if(strs[0].equals("XIAXIAN")){      //传递for(ChatThread ct : users){if(ct.nickName.equals(strs[1])){users.remove(ct);}else{ct.ps.println(strs[1]+"下线啦!");}                         }}else{for(ChatThread ct : users){ct.ps.println(msg);}                      }}catch(Exception e){}}}}   public static void main(String[] args) throws Exception   {new Server();}
}

Client4.java:

import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Client  extends JFrame implements ActionListener,Runnable {private JButton jbt = new JButton("下线");private JTextField jtf = new JTextField();private JTextArea jta = new JTextArea();private PrintStream ps = null;private BufferedReader br = null;private String nickName = null;public Client() throws Exception{this.add(jbt,BorderLayout.NORTH);this.add(jta,BorderLayout.CENTER);this.add(jtf,BorderLayout.SOUTH);jtf.addActionListener(this);jbt.addActionListener(this);jtf.setFont(new Font("宋体",Font.BOLD,30));jta.setFont(new Font("宋体",Font.BOLD,30));this.setSize(400,600);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);nickName = JOptionPane.showInputDialog("请您输入昵称");Socket s = new Socket("172.17.10.148", 9999);ps = new PrintStream(s.getOutputStream());br = new BufferedReader(new InputStreamReader(s.getInputStream()));ps.println("NICK:"+nickName);new Thread(this).start();}public void run(){while(true){try{String msg = br.readLine();jta.append(msg + "\n");}catch(Exception e){}}        }public void actionPerformed(ActionEvent e){if(e.getSource()==jtf){ps.println(nickName + "说:" + jtf.getText());}else{ps.println("XIAXIAN:" + nickName);System.exit(0);}}public static void main(String[] args) throws Exception   {new Client();}
}

另例:客户端群聊:每个客户端增加一个按钮,点击按钮,该客户端下线。其他客户端显示该客户端下线的消息——服务器要对信息进行分类处理。

9.3.3 客户端私聊案例

客户端还要显示在线客户名单,每个客户端可以选择某人,输入信息,回车发送,发送之后的信息,在指定客户端显示。

  • 每个用户登录,用户昵称发给服务器,服务器转发给客户端显示用户列表

  • 客户端选择人员之后,私聊对象的昵称发给服务器端,服务器端不再将聊天信息转发给所有客户端,而发给特定的客户端(加一个判断)

Server1.java:

import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.HashMap;
class Server  extends JFrame implements Runnable,ActionListener{private List users = new List();private JButton jbt = new JButton("远程关闭");private ServerSocket ss = null;private HashMap<String,ChatThread> cts = new HashMap<String,ChatThread>();public Server() throws Exception{this.add(users,BorderLayout.CENTER);this.add(jbt,BorderLayout.SOUTH);jbt.addActionListener(this);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setSize(200,300);this.setVisible(true);ss = new ServerSocket(9999);new Thread(this).start();}public void actionPerformed(ActionEvent e){String selectedUser = users.getSelectedItem();String msg = "LOGOUT:"+selectedUser;ChatThread ct = cts.get(selectedUser);ct.ps.println(msg);users.remove(selectedUser);cts.remove(selectedUser);}public void run(){while(true){try{Socket s = ss.accept();ChatThread ct = new ChatThread(s);}catch(Exception e){}      }}class ChatThread extends Thread{PrintStream ps = null;BufferedReader br = null;String nickName = null;ChatThread(Socket s) throws Exception{ps = new PrintStream(s.getOutputStream());br = new BufferedReader(new InputStreamReader(s.getInputStream()));this.start();}public void run(){while(true){try{String msg = br.readLine();String[] msgs = msg.split(":");if(msgs[0].equals("LOGIN")){nickName = msgs[1];users.add(nickName);cts.put(nickName,this);}}catch(Exception ex){}}}}public static void main(String[] args) throws Exception   {new Server();}
}

Client1.java:

import java.net.*;
import java.io.*;
import javax.swing.*;
class Client extends JFrame implements Runnable{private String nickName = null;private PrintStream ps = null;private BufferedReader br = null;   public Client() throws Exception{this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setSize(300,200);this.setVisible(true);nickName = JOptionPane.showInputDialog("输入昵称");Socket s = new Socket("172.17.10.147", 9999);ps = new PrintStream(s.getOutputStream());br = new BufferedReader(new InputStreamReader(s.getInputStream()));ps.println("LOGIN:"+nickName);new Thread(this).start();               }public void run(){while(true){try{String msg = br.readLine();String[] msgs = msg.split(":");if(msgs[0].equals("LOGOUT")){JOptionPane.showMessageDialog(this,"您被踢出!");this.dispose();}}catch(Exception e){}      }}public static void main(String[] args) throws Exception   {new Client();}
}

9.4 用户管理和控制

服务器可以监控各个客户端。

两个客户端输入昵称,连接到服务器,服务器显示昵称列表。选择某人,将其远程关闭

  • 定义客户端连接的信息格式为:LOGIN:昵称
  • 定义让某个客户端下线信息格式为:LOGOUT:昵称

Server1.java:

import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.HashMap;
class Server  extends JFrame implements Runnable,ActionListener{private List users = new List();private JButton jbt = new JButton("远程关闭");private ServerSocket ss = null;private HashMap<String,ChatThread> cts = new HashMap<String,ChatThread>();public Server() throws Exception{this.add(users,BorderLayout.CENTER);this.add(jbt,BorderLayout.SOUTH);jbt.addActionListener(this);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setSize(200,300);this.setVisible(true);ss = new ServerSocket(9999);new Thread(this).start();}public void actionPerformed(ActionEvent e){String selectedUser = users.getSelectedItem();String msg = "LOGOUT:"+selectedUser;ChatThread ct = cts.get(selectedUser);ct.ps.println(msg);users.remove(selectedUser);cts.remove(selectedUser);}public void run(){while(true){try{Socket s = ss.accept();ChatThread ct = new ChatThread(s);}catch(Exception e){}      }}class ChatThread extends Thread{PrintStream ps = null;BufferedReader br = null;String nickName = null;ChatThread(Socket s) throws Exception{ps = new PrintStream(s.getOutputStream());br = new BufferedReader(new InputStreamReader(s.getInputStream()));this.start();}public void run(){while(true){try{String msg = br.readLine();String[] msgs = msg.split(":");if(msgs[0].equals("LOGIN")){nickName = msgs[1];users.add(nickName);cts.put(nickName,this);}}catch(Exception ex){}}}}public static void main(String[] args) throws Exception   {new Server();}
}

Client1.java:

import java.net.*;
import java.io.*;
import javax.swing.*;
class Client extends JFrame implements Runnable{private String nickName = null;private PrintStream ps = null;private BufferedReader br = null;   public Client() throws Exception{this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setSize(300,200);this.setVisible(true);nickName = JOptionPane.showInputDialog("输入昵称");Socket s = new Socket("172.17.10.147", 9999);ps = new PrintStream(s.getOutputStream());br = new BufferedReader(new InputStreamReader(s.getInputStream()));ps.println("LOGIN:"+nickName);new Thread(this).start();               }public void run(){while(true){try{String msg = br.readLine();String[] msgs = msg.split(":");if(msgs[0].equals("LOGOUT")){JOptionPane.showMessageDialog(this,"您被踢出!");this.dispose();}}catch(Exception e){}      }}public static void main(String[] args) throws Exception   {new Client();}
}

[例1]两个客户端,每个客户端有一个图像掉下来,服务器端可以控制相应客户端暂停或继续。

定义客户端连接的信息格式为:LOGIN:昵称

  • 定义暂停为:ZT:昵称
  • 定义继续为:JX:昵称

Server2.java:

import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.HashMap;
class Server  extends JFrame implements Runnable,ActionListener{private List users = new List();private JButton jbt = new JButton("暂停");private JButton jbt2 = new JButton("继续");private ServerSocket ss = null;private HashMap<String,ChatThread> cts = new HashMap<String,ChatThread>();public Server() throws Exception{this.add(users,BorderLayout.CENTER);this.add(jbt,BorderLayout.SOUTH);this.add(jbt2,BorderLayout.NORTH);jbt.addActionListener(this);jbt2.addActionListener(this);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setSize(200,300);this.setVisible(true);ss = new ServerSocket(9999);new Thread(this).start();}public void actionPerformed(ActionEvent e){String selectedUser = users.getSelectedItem();String msg = null;if(e.getSource()==jbt){msg = "ZT:"+selectedUser;         }else{          msg = "JX:"+selectedUser;}ChatThread ct = cts.get(selectedUser);ct.ps.println(msg);        }public void run(){while(true){try{Socket s = ss.accept();ChatThread ct = new ChatThread(s);}catch(Exception e){}     }}class ChatThread extends Thread{PrintStream ps = null;BufferedReader br = null;String nickName = null;ChatThread(Socket s) throws Exception{ps = new PrintStream(s.getOutputStream());br = new BufferedReader(new InputStreamReader(s.getInputStream()));this.start();}public void run(){while(true){try{String msg = br.readLine();String[] msgs = msg.split(":");if(msgs[0].equals("LOGIN")){nickName = msgs[1];users.add(nickName);cts.put(nickName,this);}}catch(Exception ex){}}}}public static void main(String[] args) throws Exception   {new Server();}
}

Client2.java:

import java.net.*;
import java.io.*;
import javax.swing.*;
class Client extends JFrame implements Runnable{private String nickName = null;private PrintStream ps = null;private BufferedReader br = null;   private JLabel jlb = new JLabel(); private int X=100,Y = 0;private ImageThread it = null;public Client() throws Exception{this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setLayout(null);        this.add(jlb);Icon icon = new ImageIcon("img.jpg");jlb.setIcon(icon);jlb.setLocation(X,Y);       jlb.setSize(icon.getIconWidth(),icon.getIconHeight());this.setSize(300,500);this.setVisible(true);nickName = JOptionPane.showInputDialog("输入昵称");Socket s = new Socket("172.17.10.147", 9999);ps = new PrintStream(s.getOutputStream());br = new BufferedReader(new InputStreamReader(s.getInputStream()));ps.println("LOGIN:"+nickName);new Thread(this).start();       it = new ImageThread();   it.start();      }public void run(){while(true){try{String msg = br.readLine();String[] msgs = msg.split(":");if(msgs[0].equals("ZT")){it.RUN = false;}if(msgs[0].equals("JX")){it = new ImageThread();   it.start();}}catch(Exception e){}        }}class ImageThread extends Thread{boolean  RUN = true;public void run(){while(RUN){try{ Thread.sleep(100);    Y++; jlb.setLocation(X,Y);}catch(Exception ex){}}}}public static void main(String[] args) throws Exception   {new Client();}
}

[例2]两个客户端,服务器产生一个随机数,随机数从每个客户端掉下来,某一个先掉到底部,告知服务器,服务器重新产生随机数,两者同时从最上面掉下来。

定义客户端连接的信息格式为:LOGIN:昵称

  • 定义发送随机数为:SJS:数字
  • 定义掉到底部为:DB:昵称

Server3.java:

import java.net.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
import java.util.HashMap;
import java.util.Set;
class Server  extends JFrame implements Runnable{private List users = new List();private ServerSocket ss = null;private HashMap<String,ChatThread> cts = new HashMap<String,ChatThread>();public Server() throws Exception{this.add(users,BorderLayout.CENTER);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setSize(200,300);this.setVisible(true);ss = new ServerSocket(9999);new Thread(this).start();}public void run(){while(true){try{Socket s = ss.accept();ChatThread ct = new ChatThread(s);}catch(Exception e){}        }}class ChatThread extends Thread{PrintStream ps = null;BufferedReader br = null;String nickName = null;ChatThread(Socket s) throws Exception{ps = new PrintStream(s.getOutputStream());br = new BufferedReader(new InputStreamReader(s.getInputStream()));this.start();}public void run(){while(true){try{String msg = br.readLine();String[] msgs = msg.split(":");if(msgs[0].equals("LOGIN")){nickName = msgs[1];users.add(nickName);cts.put(nickName,this);}else if(msgs[0].equals("DB")){String randStr = "SJS:"+Math.random();Set<String> nickNames = cts.keySet();for(String nk : nickNames){ChatThread ct = cts.get(nk);ct.ps.println(randStr);}}}catch(Exception ex){}}}}public static void main(String[] args) throws Exception   {new Server();}
}

Client3.java:

import java.net.*;
import java.io.*;
import javax.swing.*;
class Client extends JFrame implements Runnable{private String nickName = null;private PrintStream ps = null;private BufferedReader br = null;   private JLabel jlb = new JLabel(); private int X=100,Y = 0;private ImageThread it = null;public Client() throws Exception{this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setLayout(null);        this.add(jlb);jlb.setText("欢迎参加本游戏");  jlb.setSize(200,50);jlb.setLocation(X,Y);  this.setSize(300,500);this.setVisible(true);nickName = JOptionPane.showInputDialog("输入昵称");Socket s = new Socket("172.17.10.147", 9999);ps = new PrintStream(s.getOutputStream());br = new BufferedReader(new InputStreamReader(s.getInputStream()));ps.println("LOGIN:"+nickName);new Thread(this).start();     it = new ImageThread();   it.start();      }public void run(){while(true){try{String msg = br.readLine();String[] msgs = msg.split(":");if(msgs[0].equals("SJS")){jlb.setText(msgs[1]);Y=0;                 jlb.setLocation(X,Y);}}catch(Exception e){}     }}class ImageThread extends Thread{boolean  RUN = true;public void run(){while(RUN){try{ Thread.sleep(100);    Y++; jlb.setLocation(X,Y);if(Y>=500){ps.println("DB:" + nickName);}}catch(Exception ex){}}     }}public static void main(String[] args) throws Exception   {new Client();}
}

附:《Java语言与系统设计》思维导图

考试题型:选择题、填空题、判断题、改错题、问答题、程序题。

模块 内容 要点
Java语言基本语法 Java特点 1、跨平台;2、运行的基本原理(代码用java文件,可执行文件是.class);3、语法和C基本相同,没有指针;程序入口是main函数
Java语法 1、变量、数据类型:float和long定义比较特殊;各种数据类型的精度顺序,高精度不能直接赋值给低精度;不能用0和非0表示真假;变量的定义必须掌握;字符数据类型有转义字符,用 ?表示 2、运算:算术运算:+ - * / % += -= *= /= ++ – ; 关系运算:> < >= <= == !=;逻辑运算:&&
面向对象基本概念 类和对象 类的定义(要会编程);由类来实例化对象原理;对象名的引用性质(理解对象名重新指向另一个对象的情况)
成员变量和成员函数 成员变量和成员函数的定义;通过对象访问成员变量成员函数(.号);成员函数参数传递时的值传递和引用传递的区别(需要能够分析实例)
特殊的成员变量和成员函数 1、构造函数:定义方式、调用特点、垃圾收集机制 2、函数重载:三个条件满足其一即可 3、静态变量:定义方式、性质特点、如何调用(类名.或者对象名.来调用) 4、静态函数:定义方式(和静态变量类似)、性质特点(静态函数只能访问静态成员和函数中的局部变量)、如何调用(类名.或者对象名.来调用) 常见概念的英文形式必须要掌握 需要能够进行基本的编程
面向对象基本特征 封装 1、包:定义包(注意包的嵌套关系);导入包中的类 2、类:public类(定义方式、特点);普通类(定义方式、特点) 3、成员:四个访问控制符:public、protected、默认、private 理解它们的具体权限 需要能够进行基本的编程
继承 1、如何实现继承(extends)?Java继承的特点(只能使用继承的非private成员、Java不支持多重继承) 2、覆盖:如何编程才算覆盖(子类定义成员和父类名称、返回类类型、参数皆相同)?覆盖有什么特点(子类对象调用时,直接调用子类成员)和要求(不允许减小子类成员的权限)? 3、父类构造函数的初始化(子类实例化时,会自动调用父类的构造函数,如果父类构造函数带参数,必须用super(参数列表)初始化父类对象,代码写在子类构造函数的第1句) 4、this和super的用法和意义
多态性 1、多态性的定义:父类引用指向子类对象 Dialog d = new FontDialog(); 2、性质:该引用调用重写成员时,调用的是子类成员
抽象类、接口等其他内容 1、抽象类如何定义?含有抽象函数的类,类前用abstract修饰 2、抽象类有何性质?不能被实例化;可以有普通函数;里面抽象函数必须被重写(除非子类也是抽象类) 3、接口如何定义?和抽象类有何区别?interface,用implements来实现。可以实现多个接口;接口中所有的函数都是抽象函数,并且是public;所有变量都是public的静态的final的变量(常量) 4、Object类:Java中所有类的最高父类 5、final关键字:final变量、final函数、final类特点
Java语言基本功能 异常 1、try、catch、finally:匹配规则try(1)-catch(1…)-finally(0,1);程序运行的逻辑;了解Java中常见异常类和异常原因的对应(代码预测):NullPointerException、NumberFormatException、IOException等等 2、throw、throws:掌握其使用的位置
多线程 1、定义线程(能写代码):继承Thread、实现Runnable Thread.sleep(XX);知道其用法 2、调用线程:启动线程:继承Thread、实现Runnable两类有不同的启动方法 3、控制线程:暂停和继续
基本API 1、java.lang:Math重点掌握随机数;String重点掌握字符串长度、字符串按位置访问函数;StringBuffer掌握和String的区别;基本数据类型的包装类掌握字符串和数值的互相转换 以上需要会编程 2、java.util:变长数组:List系列(子类)、Set系列(子类)、Map系列(子类);掌握其区别;需要能够用它们解决实际问题(写伪代码)
IO 1、java.io包 2、File、FileInputStream、FileOutputStream、BufferedReader、PrintStream、RandomAccessFile各自的功能(不编程)
Java语言界面开发 界面和控件 javax.swing: 界面和控件,常见的必须知道意义 java.awt:颜色和字体
布局 java.awt: FlowLayout/BorderLayout/GridLayout区别
Java事件开发 事件开发 java.awt.event包,按钮点击等简单事件用什么来监听,发出什么类型事件?
Java绘图 Graphics、paint函数作用;repaint函数作用
Java网络编程 基本概念 IP地址、端口各自区别;服务器、客户端的区别
具体实现 java.net ServerSocket\Socket各自作用;ServerSocket的accept函数的意义。

Java语言与系统设计笔记(II:从多线程开发到网络编程)相关推荐

  1. python的多线程和多进程网络编程

    二十八.python的多线程和多进程网络编程 线程和进程关系: 进程是具有独立功能的程序,进程是系统进行资源分配和调度的一个独立单位 线程是进程的一个实体,是cpu调度的基本单位,它是比进程更小的能独 ...

  2. Java语言程序设计——学习笔记(辽宁大学,王青松主讲)

    目录 一.Java基础 二.代码训练 2.1字符串 2.1.1 split()练习 2.1.2 字符串整形转换 2.1.3 判断是不是一个合法的邮箱 2.1.4 返回串sub在串s中首次出现的位置,如 ...

  3. java语言基础知识笔记

    目录 1.Java开发环境: 1)java编译运行过程:----------常见面试题 *  2)名词解释:------------------常见面试题 3)配置环境变量:------------- ...

  4. java程序设计试题_《Java语言程序设计》期末考试模拟试题——填空题和编程题...

    一.根据题意,填写出空格中的内容 Java平台包括三个技术方向,其中J2ME代表____________.J2SE代表___________.J2EE代表____________.2.面向对象的四大概 ...

  5. java听课笔记(十五)之 网络编程

    网络编程 网路应用的结构 TCP编程 TCP是一个有连接,可靠的协议 java.net.Socket java.net.ServerSocket 核心思路 开发服务器端 ServerSocket ss ...

  6. Java基础复习-八大基本数据类型-内存模型-基本算法-网络编程

    Java基础 数据类型: 基本数据类型: 整数型:byte short int long(数值型) 浮点型: float double(数值型) 字符型:char 布尔型:boolean 引用数据类型 ...

  7. linux下的C语言开发(网络编程)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 不管在Windows平台下面还是在Linux平台下面,网络编程都是少不了的.在互联网发达的今天 ...

  8. 段鹏飞java_面向对象与多线程综合实验-网络编程

    教师:段鹏飞 实验5-实验目的 了解Java网络编程基础知识;掌握java.net包中关于网络的基本类及其属性和方法;掌握基于Socket的客户和服务器编程方法. 实验内容(必做) 编写程序,将前面课 ...

  9. JAVA零学习之基础归纳(十八)--网络编程、协议、IP、基本API、URL、socket等

    [Java程序可以非常方便的访问互联网上的 HTTP服务.FTP服务等,并可以直接取得互联网上的远程资源,还可以向远程资源发送 GET.POST请求] 一.网络编程 1.1 网络概念和分类 所谓计算机 ...

最新文章

  1. js粘贴板为什么获取不到图片信息_JavaScript 学习笔记(3):图片库
  2. 【题解】luogu p1111 修复公路
  3. Ubuntu 15.04 安装 boost-python
  4. [转帖]Windows7 结束更新 以及后期更新花费。
  5. 47. Magneto Transaction Email(1)
  6. 架构之美:教你如何分析一个接口?
  7. thinkPHP开发的彩票网站源码,含pc端和手机端
  8. 古剑奇谭网络版服务器位置,《古剑奇谭网络版》【网元平台】服务器数据互通调研公告...
  9. Mysql从入门到入魔——5. 聚集、分组、子查询
  10. Elasticsearch7.13+kibana7.13安装
  11. 阅读《Keyword-Guided Neural Conversational Model》
  12. 程序员的有个坏习惯!
  13. 皮特测评:蓝牙耳机哪个品牌最好?300元内最好的蓝牙耳机
  14. 矿大计算机 学硕专硕,【20考研】超详细对比,学硕专硕如何选,不懂的学弟学妹快进来看...
  15. iS-RPA2022.1.0 | 艺赛旗RPA新版本正式发布
  16. FPGA 之 SOPC 系列(九)SOPC 补充:altera与xilinx对比
  17. 新西兰访问学者的签证材料
  18. linux中的快捷键大全
  19. 2013~2018年企业邮箱市场分析数据--市场规模、市场容量、市场份额及发展趋势...
  20. cmd命令打开mysql

热门文章

  1. LaTeX软件安装和使用说明
  2. 通过模糊测试寻找车载蓝牙的安全漏洞
  3. 头条,用户关注,收藏,评论
  4. 对每一个系,求学生的平均年龄,并把结果存入数据库中的新表dept_age(Sdept,Avg_age)中
  5. 网传字节跳动开启10-7-5工作制,员工真的不需要加班?
  6. Cook,今天我们来学做菜
  7. c语言实现的运用easyx完成的飞机大战简单小游戏(内含道具掉落,攻击转换)
  8. IP地址跨网段转换-无需网关
  9. Java汉字排序(3)按笔划排序
  10. 使用chatgpt完成简繁体转换