网络通信
局域网与因特网
服务器是指提供信息的计算机程序,客户机是指请求信息的计算机或程序。
局域网 广域网
网络协议
网络协议规定了计算机之间的物理、机械(网线与网卡的连接规定)、电气(有效的电平范围)等特征以及计算机之间的相互寻址规则、数据发生冲突的解决、长的数据如何分段传送与接受等。
1 IP协议
到目前为止,IP地址用四个字节,也就是32位的二进制数来表示,称为IPv4。为了便于使用,通常取用每个字节的十进制数,并且每个字节点用圆点隔开来表示IP地址,如192.168.1.1。
TCP/IP模式分为四层:由上到下分别为:应用层>传输层>互联网层>网络层
端口和套接字
端口是英文port的意译,可以认为是设备与外界通讯交流的出口。端口可分为虚拟端口和物理端口,其中虚拟端口指计算机内部或交换机路由器内的端口,不可见。例如计算机中的80端口、21端口、23端口等。物理端口又称为接口,是可见端口,计算机背板的RJ45网口,交换机路由器集线器等RJ45端口。电话使用RJ11插口也属于物理端口的范畴。
套接字(Socked)用于将应用程序与端口连接起来。套接字是一个假象的连接装置。
TCP程序设计基础
利用TCP协议进行通信的两个应用程序是有主次之分的,一个称为服务器程序,一个称为客户机程序。
1 服务器程序创建一个ServerSocket(服务器端套接字),调用accept()方法等待客户机连接
<1> 在指定的端口上创建服务器套接字
<2> 通过accept()方法监听客户端的连接 (该方法是一个阻塞方法如果没有客户端连接到服务器就一直保持阻塞状态)
<3> 启动一个线程进行I/O操作(每个客户端在独立的线程中执行)
2 客户端创建一个Socket,请求与服务器连接
基于HTTP协议
<1> 请求:请求行 - 命令 资源路径 协议版本号
请求头 - 键值对
空行(\r\n)
消息体- 发给服务器的数据
<2> 响应: 响应行 - 协议版本 状态码
响应头 - 键值对
空行(\r\n)
消息体 - 服务器返回的数据
3 实例<客户端与服务器之间的消息的传递>
<1> 客户端
class Test03 {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
try (Socket client = new Socket("127.0.0.1", 1234)) {
InputStream in = client.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
OutputStream out = client.getOutputStream();
PrintStream ps = new PrintStream(out);
String tempStr = scanner.nextLine();
while (!tempStr.equals("bye")) {
ps.println(tempStr);
System.out.println(br.readLine());
tempStr = scanner.nextLine();
}
}
catch(Exception e) {
e.printStackTrace();
}
scanner.close();
}
}
<2> 服务器端
class ClientHandler implements Runnable {
private Socket client;
public ClientHandler(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
InputStream in = client.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
OutputStream out = client.getOutputStream();
PrintStream ps = new PrintStream(out);
String tempStr;
while ((tempStr = br.readLine()) != null) {
if (tempStr.equals("bye")) {
client.close();
break;
}
ps.println(tempStr);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
class Test02 {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
// 1. 在指定的端口上创建服务器套接字
try (ServerSocket server = new ServerSocket(1234)) {
System.out.println("服务器已经启动...");
boolean isRunning = true;
while (isRunning) {
try {
// 2. 通过accept()方法监听客户端的连接
// 该方法是一个阻塞方法如果没有客户端连接到服务器就一直保持阻塞状态
Socket client = server.accept();
// 3. 启动一个线程进行I/O操作(每个客户端在独立的线程中执行)
// new Thread(new ClientHandler(client)).start();
service.execute(new ClientHandler(client));
}
catch (IOException e) {
e.printStackTrace();
}
}
service.shutdown();
}
catch (IOException e) {
e.printStackTrace();
}
}
}