1 回顾

  • HashMap
    • key.hashCode() 得到哈希值,用哈希值来计算下标 i
    • 键值对封装成 <mark>Enyry</mark> 实例放入 i 位置
      • 空位置,直接放入
      • 有数据,<mark>依次用key.equals()方法比较是否相等</mark>
        • 找到相等的键,覆盖值
        • 没有相等的键,用链表连接在一起
      • <mark>负载率,加载因子到0.75 (数据量/容量)</mark>
        • 新建翻倍容量的新数组
        • 所有数据重新执行哈希运算放入新数组
      • jdk1.8
        • <mark>链表长度到8,把链表转成红黑树</mark>
        • <mark>树上的数据减少到6,转回成链表</mark>

2 网络

在物理网络的基础上,建立抽象的连接

win + r, 输入 cmd

输入命令:

ipconfig

ping 192.168.21.xxx

<mark>如果ping不通,要关闭防火墙</mark>

开始—搜索防火墙

2.1 Socket 通信 - "套接字"通信

Socket - 插头

Socket - 网络套接字

  • 通过 ip 地址,两台主机可以互相找到对象
  • 在两台主机上,各选择一个端口号
    • 端口是独占的
    • <mark>0到1024是一些常见服务的默认端口</mark>
      (0000 0000 0000 ~ 0011 1111 1111 )
      • http 80
      • https 443
      • ftp 21
    • <mark>5万以后,是系统保留端口用,来自动分配</mark>
    • <mark>我们选择端口要选择 1024到5万之间的端口号</mark>


2.2 服务器端


被动等待客户端发起连接

ServerSocket 在服务器端,选择一个端口号, 在指定端口上等待客户端发起连接

ServerSocket ss = new ServerSocket(8000);

等待客户端发起连接,建立连接通道,并<mark>返回连接通道的服务器端插头对象</mark>

Socket s = ss.accept();

测试代码

package cn.edut.com.tarena.net;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server1 {
	public static void main(String[] args) throws Exception {
		int port = 8000 ; 
		ServerSocket ss = new  ServerSocket(port);
		System.out.println(port+"端口已经打开...");
		//暂停等待客户端连接。客户端连接后,会返回插在服务器端的插头对象。
		Socket s = ss.accept();
		System.out.println("客户端已连接");
		
		InputStream in = s.getInputStream();
		OutputStream out = s.getOutputStream();
		
		/* * 通信内容, * 1.接收 * Hello * 2.返回 * Hi! * Hi! */
		
		
		for(int i=0 ; i<5 ; i++) {
			char c = (char) in.read() ;
			System.out.print(c);
		}
		
		out.write("Hi!".getBytes("utf-8"));
		out.write(Byte.valueOf("Hi!"));
		out.flush();//刷出缓存
		
		s.close();
		System.out.println("连接断开。");
		ss.close();  
		System.out.println(port+"端口已经关闭。");
		
		
	}
}



2.3 客户端

主动去连接服务器

Socket s = new Socket(ip, port);

取出双向的流

InputStream in = s.getInputStream();

OutputStream out = s.getOutputStream();


2.4 超时

socket.setSoTimeout(毫秒值)

设置接收数据,等待超时时长,超时会出现 SocketTimeoutException

练习1 网络

package day17;

 

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.ServerSocket;

import java.net.Socket;

 

public class Server1 {

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

    ServerSocket ss = new ServerSocket(8000);

    System.out.println(

     "服务已经在 8000 端口上启动");

    //暂停等待客户端发起连接

    System.out.println("等待客户端连接");

    Socket s = ss.accept();

    System.out.println("客户端已连接");

    //从插头对象,获取输入流和输出流

    InputStream in = s.getInputStream();

    OutputStream out = s.getOutputStream();

    /* * 通信协议,通信流程,数据格式 * * 服务器端: * 1. 接收 "hello" * 2. 发送 "world" */

    for (int i = 0; i < 5; i++) {

        char c = (char) in.read();

        System.out.print(c);

    }

   

    out.write("world".getBytes());

    out.flush(); //刷出内存缓存

   

    s.close();//断开连接

    ss.close();//停止服务,释放端口

   

}

}

Client1

package day17;

 

import java.io.InputStream;

import java.io.OutputStream;

import java.net.Socket;

 

public class Client1 {

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

    Socket s = new Socket("旁边同学ip", 8000);

    InputStream in = s.getInputStream();

    OutputStream out = s.getOutputStream();

    /* 客户端: * 1. 发送 "hello" * 2. 接收 "world" */

    out.write("hello".getBytes());

    out.flush(); //刷出内存缓存

    for (int i = 0; i < 5; i++) {

        char c = (char) in.read();

        System.out.print(c);

    }

    s.close();

}

}


2.5 阻塞操作

ss.accept()

暂停,等待客户端发起连接

in.read()

对方不发送数据,暂停,死等数据



2.6 服务器端的线程模型

练习2 回声

客户端发送到服务器的数据,原封不动的发回客户端

EchoServer

package day17;

 

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

 

public class EchoServer {

public void launch() {

    new Thread() {

        @Override

        public void run() {

           try {

              ServerSocket ss = new ServerSocket(8000);

              System.out.println("服务已在 8000 端口上启动");

              while(true) {

                 System.out.println("等待下一个客户端连接");

                 Socket s = ss.accept();

                 System.out.println("客户端已连接");

                 TongXinThread t = new TongXinThread(s);

                 t.start();

              }

           } catch (Exception e) {

              System.out.println(

               "无法在 8000 端口上启动服务,或服务已停止");

           }

        }

    }.start();

}



class TongXinThread extends Thread {

    Socket s;

    public TongXinThread(Socket s) {

        this.s = s;

    }

    @Override

    public void run() {

        /* * 通信协议,流程和格式 * UTF-8编码的字符串, * 每段字符串末尾添加换行 * * BR--ISR--网络输入流 * PW--OSW--网络输出流 */

       

        try {

           BufferedReader in =

            new BufferedReader(

            new InputStreamReader(

            s.getInputStream(), "UTF-8"));

           PrintWriter out =

            new PrintWriter(

            new OutputStreamWriter(

            s.getOutputStream(),"UTF-8"));

           String line;

           while((line = in.readLine()) != null) {

              out.println(line);

              out.flush();

           }

           //断开

        } catch (Exception e) {

           //断开

        }

       

        System.out.println("一个客户端端已断开");

       

    }

}



public static void main(String[] args) {

    EchoServer s = new EchoServer();

    s.launch();

}

}

EchoClient

package day17;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import java.io.PrintWriter;

import java.io.UnsupportedEncodingException;

import java.net.Socket;

import java.util.Scanner;

 

public class EchoClient {

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

    Socket s = new Socket("找一个人启动服务器", 8000);

    BufferedReader in =

     new BufferedReader(

     new InputStreamReader(

     s.getInputStream(), "UTF-8"));

    PrintWriter out =

     new PrintWriter(

     new OutputStreamWriter(

     s.getOutputStream(),"UTF-8"));   

    while(true) {

        System.out.print("输入:");

        String str = new Scanner(System.in).nextLine();

        out.println(str);

        out.flush();

        String echo = in.readLine();

        System.out.println("回声:"+echo);

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

    }

}

}