Java学习日志Day27_TCP的三次握手_反射_mySql

一、TCP/IP的反馈

举例1public class ClientTest {
    public static void main(String[] args) throws IOException {
        //创建客户端的Socket对象
        Socket socket = new Socket("10.12.152.129",10010) ;

        //获取通道内的输出流
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("我给你打招呼".getBytes());


        //读取服务器端的反馈数据
        //获取当前客户端的所在的通道 的输入流
        InputStream inputStream = socket.getInputStream();
        byte[] bytes = new byte[1024] ;
        int len = inputStream.read(bytes);
        System.out.println("服务器反馈数据是:"+new String(bytes,0,len));

        //释放资源
        socket.close();
    }
}

public class ServerTest {

    public static void main(String[] args) throws IOException {

        //创建服务器端的Socket对象
        ServerSocket ss = new ServerSocket(10010) ;

        //侦听
        Socket socket = ss.accept(); //获取客户端的套接字(Socket对象)
        InputStream in = socket.getInputStream();

        //一次读取一个字节数组
        byte[] bytes = new byte[1024] ;
        int len = in.read(bytes);
        System.out.println("数据来自于 :"+socket.getInetAddress().getHostAddress()+
                ",当前客户端发送的内容是:"+new String(bytes,0,len));


        //服务器端要反馈(确认字符 :(syn+ack)包)
        //获取通道内内的输出流
        OutputStream out = socket.getOutputStream();
        out.write("数据已经收到,请您那边确认".getBytes());

        //释放资源
        ss.close();

    }
}

二、TCP/IP的三次握手

三次握手

举例:
/* 客户端一个文本文件(ServerTest.java),通过服务器端将这个文件进行复制到当前项目的copy.java文件中
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {

        //创建客户端Socket对象
        Socket socket = new Socket("10.12.152.129",8888) ;

        //读这个文本文件:使用字符缓冲输入流BufferedReader
        BufferedReader br = new BufferedReader(new FileReader("ServerTest.java")) ;
        //封装通道内的字节输出流
        BufferedWriter bw  =
                new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())) ;

        //读一行,给通道内包装的字符输出流中写入内容
        String line = null ;
        while((line=br.readLine())!=null){
            //写一行到当前通道内中
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        br.close();
        socket.close();

    }
}

/* 通过服务器端将这个文件进行复制到当前项目的copy.java文件中
 */
public class ServerDemo {

    public static void main(String[] args) throws IOException {

        //创建服务器端的Socket对象
        ServerSocket ss = new ServerSocket(8888) ;

        Socket socket = ss.accept();
        //封装通道内的基本字节输入流
        BufferedReader br =
                new BufferedReader(new InputStreamReader(socket.getInputStream())) ;

        //输出一个文件:Copy.java:当前项目下
        BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));


        //一次读取一行
        String line = null ;
        while((line=br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //关闭资源
        bw.close();
        ss.close();

    }
}

三、反射:

  1. 什么是反射?
    反射就是获取一个类的字节码文件,然后加载该类的所有的成员
    成员变量所在类---->Field
    成员方法所在类---->Method
    构造方法所在类—>Constructor
    给成员变量赋值通过Field,调用成员方法Method,通过构造器创建的对象…
  2. 获取一个类的字节码文件 (三种)
/ *  Class:
 *          public static Class<?> forName(String className):参数为当前类的全限定名称
 *                         throws ClassNotFoundException
 */
public class RelectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {

        //获取一个类的字节码文件对象
        //1)Object类的getClass()
        Person p = new Person() ;
        Class c1 = p.getClass();
        System.out.println(c1);//class 包名.类名
        //Integer-->java.lang.Integer

        //Class
        //public String getName()
        System.out.println(c1.getName());//获取当前Person类的全限定名称 com.qf.reflect_01.Person
        System.out.println("-------------------------");

        //2)任意Java类型的class属性
        Class c2 = Person.class ;
        System.out.println(c2);
        System.out.println(c2.getName());
        System.out.println(c1==c2);


        System.out.println("-------------------------");

        //3)Class的静态功能
        Class c3 = Class.forName("com.qf.reflect_01.Person") ;
        System.out.println(c3);//class com.qf.reflect_01.Person
    }
}
举例:
public class Person {
    public String name ;//默认的修饰符
    private int age ;//私有的成员变量
    String address ; //默认的修饰符
    
    public Person(){} //公共的构造方法

    private Person(String name,int age){
        this.name = name ;
        this.age = age ;
    }
 //默认的修饰
    Person(String name,int age,String address){
        this.name = name ;
        this.age = age;
        this.address = address ;
    }

    //成员方法
    public String show(){
       return "show Person";
    }

    private String function(int number){
        return "hello,JavaEE"+number ;
    }

    String method(){
        return "mysql" ;
    }


    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}
  1. 通过反射获取一个类的构造器并且创建当前类对象呢
 * 之前的写法:
 *      Person perons = new Person() ;
 */
public class Reflect_getCon {
    public static void main(String[] args) throws Exception {

        //1)获取指定的类的字节码文件对象: com.qf.reflect_01.Person的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person") ;

        //2)通过字节码文件对象获取构造器(Constructor)
        //public Constructor<?>[] getConstructors() throws SecurityException
        //获取类的所有公共的构造方法
       // Constructor[] constructors = clazz.getConstructors();
        //public Constructor<?>[] getDeclaredConstructors():可获取当前类中的所有构造方法(包括私有以及默认)
        /*Constructor[] constructors = clazz.getDeclaredConstructors();
        for(Constructor con:constructors){
            System.out.println(con);
            *//**
             * public com.qf.reflect_01.Person() :
             *
             *
             * com.qf.reflect_01.Person(java.lang.String,int,java.lang.String)
             * private com.qf.reflect_01.Person(java.lang.String,int)
             * public com.qf.reflect_01.Person()
             *//*
        }*/

        //通过字节码文件对象获取单个构造方法:公共的
        //参数为:可变参数 ...(类似于数组:参数可以有很多个)
        //如果存在参数:必须参数类型的Class     String   ---->java.lang.String
                //Person(String name,Integer i)---->参数:java.lang.String, java.lang.Integer
        //无参的构造方法:不需要传参
        //public Constructor<T> getConstructor(Class<?>... parameterTypes)
        Constructor con = clazz.getConstructor() ;


        //获取了构造器之后:通过构造器创建当前类的实例
        // public T newInstance(Object... initargs):参数是给构造方法中赋值的实际参数

        Object obj = con.newInstance();
        System.out.println(obj);


        System.out.println("--------------------");

        //之前写法
        Person p = new Person() ;
        System.out.println(p);

       // Person p1 = new Person("高圆圆",20) ;

    }
}
  1. 通过反射获取指定的构造方法(非公共),并创建该类实例
/* 私有的构造方法不能直接new的
 */
public class Reflect_getCon2 {

    public static void main(String[] args) throws Exception {

        //获取Person类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person");


        //获取指定的构造方法:Constructor
        //private Person(String name,int age)
        //获取指定的构造方法(包括私有),参数为当前参数类型的字节码文件对象
       // public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

        Constructor con = clazz.getDeclaredConstructor(String.class,int.class) ;

        //Constructor:构造器 Method:成员方法,Field:成员变量
        //公共的基类:AccessibleObject
        //public void setAccessible(boolean flag):取消Java语言访问检查 (参数为true)

        con.setAccessible(true);

        //创建当前类的实例
        //        Object obj =  con.newInstance("高圆圆",41) ;
        //        System.out.println(obj);//Person的toString方法
        //        //Person{name='高圆圆', age=41, address='null'}
        System.out.println("----------------------------");

//      Person p = new Person("高圆圆",41) ;//已经私有化

    }
}
举例:
/* 访问Person类的默认修饰符的构造方法,并且创建当前类实例
 * 类似于  Person p = new Person("高圆圆",41,""西安) ;
 */
public class Refelect_getCon3 {
    public static void main(String[] args) throws Exception {
        //获取当期类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person") ;
        //获取构造器Constructor
        Constructor con =  clazz.getDeclaredConstructor(String.class,int.class,String.class) ;

       //构造方法:默认修饰符
        //取消Java语言访问检查
        con.setAccessible(true);

        //创建该类实例
        Object obj = con.newInstance("高圆圆",41,"鄠邑区") ;
        System.out.println(obj);

    }
}
  1. 通过反射方式获取成员变量Field,并给其进行赋值!
举例:
/* 之前的写法:
 *      //通过无参构造方法创建UI小
 *      Person person = new Person() ;
 *      person.setName("高圆圆") ;
 *      person.setAge(41) ;
 */
public class ReflectDemo {

    public static void main(String[] args) throws  Exception{
        //1)获取指定的类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person") ;

        //方式1:通过无参构造器创建实例
        //2)通过反射获取单个公共的构造方法,无参
       /* Constructor constructor = clazz.getConstructor();
        //System.out.println(constructor);
        //3)通过构造器创建当前类实例
        Object obj = constructor.newInstance();
        System.out.println(obj);*/

       //方式2:直接创建当前类实例
       //Class类的功能:直接通过当前类的字节码文件对象创建当前类对象
        //public T newInstance()
        Object obj = clazz.newInstance();
        System.out.println(obj);

        //public Field[] getFields():获取当前类或者指定接口中的所有的公共的字段
        //public Field[] getDeclaredFields():获取当前类中所有的字段(公共的,受保护的,私有的,默认的)
       // Field[] fields = clazz.getFields();
       /* Field[] fields  =clazz.getDeclaredFields() ;
        for(Field field:fields){
            System.out.println(field);
            //公共的字段(成员变量)
            //public java.lang.String com.qf.reflect_01.Person.name

            *//**
             * public java.lang.String com.qf.reflect_01.Person.name
             * private int com.qf.reflect_01.Person.age
             * java.lang.String com.qf.reflect_01.Person.address
             *//*
        }*/

        //获取指定的单个的字段(成员变量):公共字段
        //name:公共的字段
        //public Field getField(String name):参数名称为"成员变量名称"
        Field nameField = clazz.getField("name");
        //给当前Field所代表的的指定的字段name来进行赋值
//        public void set(Object obj,Object value)
        //将指定的值绑定在当前类的实例上
        nameField.set(obj,"高圆圆");

        //age:私有的属性
        //address:默认修饰符
        //在设置值之前,需要取消Java语言访问检查

        System.out.println(obj);

        System.out.println("---------------------");

        //获取age所在的Field对象,为其赋值
        //Field getDeclaredField(String name):获取指定的字段Field
        Field ageField = clazz.getDeclaredField("age");

        //取消Java语言访问检查
        //私有属性
        ageField.setAccessible(true);
        //赋值
        ageField.set(obj,41);
        System.out.println(obj);

        System.out.println("----------------------------");
        Field addressField = clazz.getDeclaredField("address");
        addressField.setAccessible(true);
        addressField.set(obj,"西安市");
        System.out.println(obj);
    }
}
举例:
public class Student {
    public void love(){
        System.out.println("爱学习,爱Java");
    }
}

public class Worker {
    public void love(){
        System.out.println("爱生活,爱敲代码...");
    }
}

class.properties:
className=com.qf.reflect_04.Worker
methodName=love

/* 通过反射方式来调用Person类中的成员方法(非静态的)
 */
public class ReflectDemo {

    public static void main(String[] args) throws Exception{

        //获取Person类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person");

        //获取当前类的所有的公共的成员方法:有自己的,还有继承的
        //public Method[] getMethods()
        //public Method[] getDeclaredMethods():获取类或者接口中的指定的成员方法(公共,默认,私有,受保护)
       /* Method[] methods = clazz.getDeclaredMethods() ;

//        Method[] methods = clazz.getMethods();
        for(Method method :methods){
            System.out.println(method);
        }*/


       //之前的写法:
        //无参构造方法创建对象:
        //Person p = new Person() ;
        // p.show() ;
        Constructor con = clazz.getConstructor();
        //创建Person类的实例
        Object obj = con.newInstance();

        //通过反射获取成员方法所代表的的Method对象
        //获取公共的成员方法
        //参数1:方法名
        //参数2:当前该方法的形式参数类型的Class
        //public Method getMethod(String name ,Class<?>... parameterTypes)
        Method showMethod = clazz.getMethod("show");
        //要执行showMethod方法: show()

        //Method
        //参数1:当前类的实例
        //参数2:给方法形式参数传递的实际参数
        //返回值:就是调用当前方法本身的时候,如果方法是没有具体返回值,那么直接单独调用
        //如果有返回值类型,那么就使用Object来结束即可!

        //public Object invoke(Object obj, Object... args):
        Object returnObj = showMethod.invoke(obj);
        System.out.println(returnObj);


        System.out.println("----------------------");
        //获取function方法并调用
        //Method getDeclaredMethod(String name,Class...parameterNames)
        //获取指定的Method
        Method functionMethod = clazz.getDeclaredMethod("function", int.class);
        //取消Java语言访问检查
        functionMethod.setAccessible(true);

        Object retunrObj2 = functionMethod.invoke(obj, 27);
        System.out.println(retunrObj2);

        System.out.println("----------------------");
        Method methodM = clazz.getDeclaredMethod("method") ;
        methodM.setAccessible(true );
        Object returnObj3 = methodM.invoke(obj);
        System.out.println(returnObj3);

     /*   Person p = new Person() ;
        System.out.println(p.show());*/
        //通过反射调用function方法以及method 方法
    }
}

反射的应用1:

举例:
/* 面试题
 *      现在有一个ArrayList<String>,如何实现给里面存储Integer类型呢?
 *
 *     可以,通过反射方式操作:-----获取Class---->Method--->invoke(当前类实例,方法实际参数)
 */
public class Test {
    public static void main(String[] args) throws Exception {
        //创建一个ArrayList<String>
        ArrayList<String> array = new ArrayList<String>() ;
        array.add("hello") ;
        array.add("world") ;
        array.add("javaee") ;
        System.out.println(array);
        System.out.println("--------------------");
       // array.add(100) ;

        //通过反射方式调用add方法
        //Object的getClass()获取字节码文件对象
        Class clazz = array.getClass() ;
        //clazz创建当前类实例
        Object obj = clazz.newInstance();//通过反射创建

        //获取Method对象:方法名 add
        Method addMethod = clazz.getMethod("add", Object.class);
        //调用方法
        addMethod.invoke(obj,"mysql") ;
        addMethod.invoke(obj,100) ;
        addMethod.invoke(obj,50) ;

        System.out.println(obj);
    }
}

反射的应用2:

举例:
/* Class.forName("全限定名称"):参数为字符串:被经常用在配置文件中
 */
public class Test2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException,
            IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        //创建一个学生类
        Student s = new Student() ;
        s.love();
        //代码不断变化
        //工人类
        Worker worker = new Worker() ;
        worker.love();

        //Java设计开发原则:
                //开闭原则: 对现有代码的修改关闭,在现有代码基础进行扩展!

        System.out.println("-----------------------------------");

        //提供了一个扩展:在src下(类路径下)配置文件class.properties
        //读取配置文件获取里面keyvalue属性列表,将它载入到Properties属性集合类中
        InputStream inputStream = Test2.class.getClassLoader().
                getResourceAsStream("class.properties");

        //创建属性集合列表
        Properties prop = new Properties() ;
        prop.load(inputStream);
        System.out.println(prop);

        //通过key获取value
        String className = prop.getProperty("className");
        String methodName = prop.getProperty("methodName");

        //反射获取当前className里面的类的字节码文件对象
        Class clazz = Class.forName(className) ;
       // System.out.println(clazz);
        //直接当前类实例
        Object obj = clazz.newInstance();

        //反射获取Method对象
        Method method = clazz.getMethod(methodName);
        method.invoke(obj) ;
    }
}

四:mySql

mySql

  1. 什么是数据库?
    存储数据的仓库!
  2. 特点:
    永久存储
    可以支持一些事务
    (数据库的事务----将整个业务操作看成一个整体:转账(要么一起成功,要么一起失败!))
    执行效率高(通过sql语句)

之前存储方式:
1)临时变量 存储在内存中,方法结束 局部变量就消失了
2)数组 存储同一种类型元素,但是长度固定的!
3)StringBuffer: 字符串缓冲区 :里面存储的可变的字符序列
4)集合 存储任意类型元素,必须引用类型
取元素: 遍历 (单例集合:Iterator)
增强for循环
存储大量大数据,效率太低
5)IO流:也能存储数据
太耗时(读写过程)
3. 常见的数据库:
关系型数据库:
oracle: 针对JavaEE支持的(java平台),收费 (大型公司:金融行业:银行)
中国银行: 现在技术----SpringCloud
mysql:开源的而且免费(针对中小型公司使用居多)
相同的数据库引擎:MariaDB

		SqlServer:针对net平台更兼容一些(收费的)
NoSQL:非关系数据库

	 key-value
	 
	 代表:redis---->分布式缓存:可以缓存用户:User
					缓存相关商品数据/缓存一些经常改变的数据
	      MangoDb
  1. Mysql:
    必须安装mysql软件----一台计算机如果按照了mysql软件(mysql服务器)
    安装版:5.5
    1)安装软件
    2)配置信息
    a) 勾选path—勾选上:自动给配置mysql的path环境配置
    b)选择编码集: utf8(最好使用这个格式)
    如果gbk 在dos中使用mysql客户端的时候,中文的就会出现乱码
    用户名:root:管理员用户
    密码:root/自己定义(不要太简单),后期可能没有权限访问–
    只能通过mysql的权限命令重写设置密码
    登录
    thougtWorks(外企:思特沃克)
    华为:deeplin(深度Linux系统)
    —配置:Mac本
    Mac本:按照idea
    maven工具
    Linxu系统
    使用进入dos控制台进行登录(黑窗口去使用)
C:\Users\zhangyang>mysql -uroot -p
Enter password: ******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 5.5.40 MySQL Community Server (GPL)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>		
  1. DDL语句:
    操作数据库

1). 查询当前服务器软件中的所有的数据库

show databases;
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |-- mysql服务器相关的配置
| mysql              |-- 存储很多相关的用户表user(权限用户)
| performance_schema |-- 跟mysql性能优化相关的表信息
| test               |-- 测试数据库
+--------------------+				

2). 创建新的数据库

create database 数据库名称;
create database if not exists 数据库名称;

mysql> create database if not exists EE_2104;
Query OK, 1 row affected (0.01 sec)

3). 查看创建的数据库的默认字符集

show create database 数据库名称;
 mysql> show create database ee_2104;
+----------+------------------------------------------------------------------+
| Database | Create Database                                                  |
+----------+------------------------------------------------------------------+
| ee_2104  | CREATE DATABASE `ee_2104` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+------------------------------------------------------------------+
1 row in set (0.00 sec)

4). 修改数据库的默认字符集

alter database 数据库名称 DEFAULT(可以省略) CHARACTER SET 字符集;
mysql> alter database ee_2104 character set gbk;
Query OK, 1 row affected (0.00 sec)

mysql> show create database ee_2104;
+----------+-----------------------------------------------------------------+
| Database | Create Database                                                 |
+----------+-----------------------------------------------------------------+
| ee_2104  | CREATE DATABASE `ee_2104` /*!40100 DEFAULT CHARACTER SET gbk */ |
+----------+-----------------------------------------------------------------+ 

5). 删除数据库

drop database 数据库名称;
drop database if exists 数据库名称;
mysql> drop database if exists ee_2104;
Query OK, 0 rows affected (0.00 sec)

6). 切换数据库(数据库本身就是一个文件夹,进入到某个文件夹中)

use 数据库名称;
mysql> use ee_2104;
Database changed

7). DDL语句:来操作表

mysql> show tables; 查询当前指定数据库中的所有表
Empty set (0.01 sec)

8). 创建表的语法:

create table 表名(
			字段名称1 字段类型1,
			字段名称2 字段类型2,
			字段名称3 字段类型3,
			....
			字段名称n 字段类型n
		);

9). mysql常见的字段类型
int:整数类型(推荐):默认11位
当给定的值,它获取到当前整数的实际长度(自动获取)

age int,----age = 50

int(位数):不推荐

int(4)  ---age = 5       0005

varchar(指定长度):就是java类的String 字符串类型:推荐使用’’,也可以双引号 ,也可以不带引号

举例
					name varchar(20):name字段最大能支持20个字符

date:日期 : 仅仅只是表示日期,没有时间
datetime:日期+当前时间
timestap:时间戳 (就当前被访问/操作具体:当前系统时间)
double(5,3):小数类型,可以5位数据,小数点后3位…
double 小数类型:100 —>100.0

mysql> create table student(
    -> sid int,
    -> name varchar(10),
    -> age int,
    -> address varchar(10),
    -> gender varchar(5),
    -> birthday date
    -> );
Query OK, 0 rows affected (0.02 sec)

10). 查询表的结构:desc 表名;

mysql> desc student;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| sid      | int(11)     | YES  |     | NULL    |       |
| name     | varchar(10) | YES  |     | NULL    |       |
| age      | int(11)     | YES  |     | NULL    |       |
| address  | varchar(10) | YES  |     | NULL    |       |
| gender   | varchar(5)  | YES  |     | NULL    |       |
| birthday | date        | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
6 rows in set (0.03 sec)					

11). 修改表:
给表中添加一列(添加一个字段)
alter table 表名 add 字段名称 字段类型;

mysql> alter table student add hobit varchar(20);
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0			
mysql> desc student;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| sid      | int(11)     | YES  |     | NULL    |       |
| name     | varchar(10) | YES  |     | NULL    |       |
| age      | int(11)     | YES  |     | NULL    |       |
| address  | varchar(10) | YES  |     | NULL    |       |
| gender   | varchar(5)  | YES  |     | NULL    |       |
| birthday | date        | YES  |     | NULL    |       |
| hobit    | varchar(20) | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+			

12). 修改表的字段名称

alter table 表名 change 以前的列名称 新的列名称 以前的字段类型;			
mysql> alter table student change gender sex varchar(5);
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc student;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| sid      | int(11)     | YES  |     | NULL    |       |
| name     | varchar(10) | YES  |     | NULL    |       |
| age      | int(11)     | YES  |     | NULL    |       |
| address  | varchar(10) | YES  |     | NULL    |       |
| sex      | varchar(5)  | YES  |     | NULL    |       |
| birthday | date        | YES  |     | NULL    |       |
| hobit    | varchar(20) | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
7 rows in set (0.02 sec)

13). 修改表的字段类型

alter table 表名 modify 字段名称 更改后的字段类型;
mysql> alter table student modify sex varchar(3) ;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc student;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| sid      | int(11)     | YES  |     | NULL    |       |
| name     | varchar(10) | YES  |     | NULL    |       |
| age      | int(11)     | YES  |     | NULL    |       |
| address  | varchar(10) | YES  |     | NULL    |       |
| sex      | varchar(3)  | YES  |     | NULL    |       |
| birthday | date        | YES  |     | NULL    |       |
| hobit    | varchar(20) | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
7 rows in set (0.02 sec)

14). 修改的表的名称

alter table 以前表名 rename to 新表名;
mysql> alter table student rename to stu;
Query OK, 0 rows affected (0.01 sec)

mysql> show tables;
+-------------------+
| Tables_in_ee_2104 |
+-------------------+
| stu               |
+-------------------+
1 row in set (0.02 sec)

15). 创建表的时候复制一张相同的表

create table 新表名 like 存在的表名; 
mysql> create table teacher like stu;
Query OK, 0 rows affected (0.02 sec)

mysql> show tables;
+-------------------+
| Tables_in_ee_2104 |
+-------------------+
| stu               |
| teacher           |
+-------------------+
2 rows in set (0.00 sec)

mysql> desc teacher;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| sid      | int(11)     | YES  |     | NULL    |       |
| name     | varchar(10) | YES  |     | NULL    |       |
| age      | int(11)     | YES  |     | NULL    |       |
| address  | varchar(10) | YES  |     | NULL    |       |
| sex      | varchar(3)  | YES  |     | NULL    |       |
| birthday | date        | YES  |     | NULL    |       |
| hobit    | varchar(20) | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
7 rows in set (0.01 sec)

16). 删除表

drop table 表名;
drop table if exists 表名;
mysql> drop table teacher;
Query OK, 0 rows affected (0.02 sec)

五:案例:聊天室

思路
聊天室涉及的功能:
1)注册用户(登录)
2)公聊
3)私聊
4)上下线提醒
5)发送文件…

客户端工程和服务器端工程

通过TCP方式:
客户端不断发送数据,服务器端不断的使用数据,并且
服务器端不断的反馈数据到客户端,客户端不断的读取数据!

问题1:
客户端 :发消息和读消息都在主线程中
服务器端:读消息和反馈(回复)消息也是在线程中

思考:是将读消息放在线程中还是写消息放在子线程中?

问题2:问题1可能会导致----互相阻塞现象
假设:
客户端将一个100M图片文件将这个文件内容读取完毕,通过通道内的 输出流写给服务器端
服务器端将图片读出来复制在指定xxx.jpg文件中

字节流的方式读— -1是作为读取完毕的条件, 客户端并不知道文件是否读完!
互相等待:
客户端等待服务器端反馈,文件复制完毕
而服务器端等待客户端 通知他(文件已经复制完了)
优化思想

客户端:
public class ChatRoomClient {

    public static void main(String[] args) {

        //创建客户端的Socket对象
        Socket socket = null ;
        try {
           socket = new Socket("10.12.152.129",6666) ;
            //获取当前客户端所在的通道内的输入和输出流
            InputStream in = socket.getInputStream();
            OutputStream out = socket.getOutputStream();

            //创建键盘录入对象
            Scanner sc = new Scanner(System.in) ;


            //开启读取服务器转发的消息的子线程
            ClientThread ct  = new ClientThread(in) ;
            ct.start();


            while(true){

                //不断的去录入数据,将数据写过去
                System.out.println("请您输入消息:");
                String clientMsg = sc.nextLine() ;
                //自定义结束条件  :发送一个图片文件:100m

                //约定的消息格式:
                // 接收者:消息内容:发送者

                out.write(clientMsg.getBytes());


                //不断的去读取服务器端反馈的消息
           /*     byte[] bytes = new byte[1024] ;
                int len = in.read(bytes);
                String reveiveFk = new String(bytes,0,len) ;
                System.out.println(reveiveFk);*/
//                思考:是将读消息放在线程中还是写消息放在子线程中?
                //将读消息放在子线程中,子线程不能录入消息的!
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
客户端子线程
/* 客户端读取消息(服务器转发消息)的子线程
 */
public class ClientThread extends Thread {
    private InputStream in;
    public ClientThread(InputStream in){
        this.in = in ;
    }

    @Override
    public void run() {
        try{
            //不断读取 服务器转发的消息
            while(true){
                byte[] bytes = new byte[1024] ;
                int len = in.read(bytes);
                String reveiveFk = new String(bytes,0,len) ;
                System.out.println(reveiveFk);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
服务器端:
/* 服务器端的主线程中
 */
public class ChatRoomServer {

    public static void main(String[] args) {

        //创建服务器端的Socket对象,绑定指定的端口号
        try {
            ServerSocket ss = new ServerSocket(6666) ;
            //创建ArrayList<Socket>
            ArrayList<Socket> list = new ArrayList<Socket>() ;
            System.out.println("服务器正在等待连接");
            //定义一个变量
            int i = 1 ;
            //不断的监听的多个客户端
            while(true){
                //监听客户端并获取客户端的socket
                Socket socket = ss.accept();
                System.out.println("第"+(i++)+"个客户端已经连接...");
                list.add(socket) ;

                //获取通道的内输入和输出流
               /*
                OutputStream out = socket.getOutputStream();*/
                InputStream in = socket.getInputStream();

                //开启一个读取消息的子线程
//                ServerThread st  = new ServerThread(socket) ;
                ServerThread st  = new ServerThread(in,list) ;
                //启动线程
                st.start();
            }
            
            //创建键盘录入对象
         //   Scanner sc  = new Scanner(System.in) ;

            //不断去读取客户端发送的消息
           /* while(true){
                //读取客户端发送的消息

                //下面代码需要开子线程
                byte[] bytes = new byte[1024] ;
                int len = in.read(bytes);
                String receiveClientMsg = new String(bytes,0,len) ;
                System.out.println(receiveClientMsg);

                //不断的回复消息(反馈)
                //服务器不回复消息
               *//* System.out.println("请回复消息:");
                String serverMsg = sc.nextLine() ;
                out.write(serverMsg.getBytes());*//*
            }*/

        } catch (IOException e) {
            e.printStackTrace();
        }
        //服务器端不关闭
    }
}
服务器类子线程:
/* 服务器读取消息的子线程
 */
public class ServerThread extends  Thread {

    private InputStream in ;
    private ArrayList<Socket> list ;
    public ServerThread(InputStream in,ArrayList<Socket> list){
        this.in = in ;
        this.list = list ;
    }
    /*private Socket socket ;
    public ServerThread(Socket socket){
        this.socket = socket ;
    }*/

    //重写run方法
    @Override
    public void run() {
        try{
            //读数据的操作
            //不断读取
            while(true){
                byte[] bytes = new byte[1024] ;
                int len = in.read(bytes);
                String receiveClientMsg = new String(bytes,0,len) ;
                System.out.println(receiveClientMsg);//测试

                //拆分消息:"接收者:消息内容:发送者"
                //        1:  消息内容:0
                String[] msgStr = receiveClientMsg.split(":");
               // String receiver = msgStr[0] ;   String类型----> int:Integer.parsetInt(msgStr[0])
              //  String content = msgStr[1] ;
              //  String sender = msgStr[2] ;

                //ArrayList<Socket>    list集合对.get(角标)--->某个客户端的Socket对象

                //获取接收者所在的通道内的输出流,写过去
                OutputStream outputStream = list.get(Integer.parseInt(msgStr[0])).getOutputStream();

                //重新组装消息
                outputStream.write((msgStr[2]+"对你说 "+msgStr[1]).getBytes());
            }
        }catch (Exception e){
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

igfff

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值