网络编程的常识

  • 七层网络模型

    OSI(Open System Interconnect),即开放式系统互联,是ISO(国际标准化组织)在1985年研究的网络互连模型.

    OSI七层模型和TCP/IP五层模型:


当发送数据时,按照上述七层协议从前向后一层层进行加包处理再发送;

当接收数据时,按照上述七层协议从后向前一层层进行拆包处理再显示;

  • IP地址

    如:192.168.1.1 - 是绝大多数路由器的默认登录地址,设置账号和密码及Mac地址过滤

    IP地址 - 是互联网中的唯一地址标识,根据IP地址可以定位到具体某一台设备。

    IP地址本质上是由32位二进制组成的整数,叫做IPv4,当然也有128位二进制组成的整数,叫做IPv6,目前的主流还是IPv4。

    日常生活中采用点分十进制表示法进行IP地址的描述,也就是将每个字节的二进制整数转换为一个十进制整数,不同的十进制整数之间采用小数点隔开。

    如: 0x01020304 => 1.2.3.4

    IP地址其实就是一个虚拟的整数,本身和计算机没有关系.实际上IP地址是绑定了网址的物理地址(Mac),网卡的物理地址是出厂就设定,无重复.IP地址其实找到的是网卡.

  • 端口号

    端口号 - 是设备中具体进程的标识,也就是根据端口号可以定位到具体某个进程。

    网络编程提供:IP地址 + 端口号。

    端口号本质上是由16位二进制组成的整体,表示范围是:0-65535,其中0-1024之间的端口号通常被系统占用,因此编程从1025开始使用。

    特殊端口: HTTP:80 FTP:21 Oracle:1521 Mysql:3306 Tomcat:8080

基于tcp协议的编程模型(重点)

  • C/S架构的简介

    在C/S模式下客户向服务器发出服务请求,服务器接收到请求后提供相应服务。

    客户端:为每个用户所专有的,负责执行前台功能。

    服务器:由多个用户共享的信息与功能,招待后台服务。

  • ServerSocket类

    主要用于描述服务器套接字信息。

    ServerSocket(int port) - 根据参数指定的端口号来构造对象.

    Socket accept() - 侦听并接收到此套接字的连接请求.

    void close() - 用于关闭套接字.

  • Socket类

    Socket(String host,int port) - 根据指定主机名和端口来构造对象.

    InputStream getInputStream() - 用于获取当前套接字的输入流.

    OutputStream getOutputStream() - 用于获取当前套接字的输出流.

    void close() - 用于关闭套接字.

  • 编程模型


服务器:

(1)创建ServerSocket类型的对象并提供端口号;

(2)等待客户端的连接请求,调用accept方法;

(3)使用输入输出流通信;

(4)关闭Socket;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.net.ServerSocket;
import java.net.Socket;
public class ServerStringTest {
public static void main(String[] args) {
try {
// 1.构造ServerSocket类型的对象并提供端口号
ServerSocket ss = new ServerSocket(8888);
// 2.等待客户端的连接请求,调用accept方法
while(true) {
System.out.println("等待客户端的连接请求...");
Socket s = ss.accept();
System.out.println("客户端" + s.getInetAddress()
+"连接成功!");
// 只要有客户端连接成功,就启动一个新线程为之服务
new ServerThread(s).start();
}
//ss.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
public class ServerThread extends Thread {
private Socket s;
public ServerThread(Socket s) {
this.s = s;
}
@Override
public void run() {
try {
// 3.使用输入输出流进行通信
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintStream ps = new PrintStream(s.getOutputStream());
while (true) {
// 接收客户端发来的字符串内容,BufferedReader类
String msg = br.readLine();
//System.out.println("服务器接收到的数据内容是:" + msg);
InetAddress ia = s.getInetAddress();
System.out.println("客户端" + ia + "发来的数据内容是:" + msg);
// 判断服务器接收到的消息是否为"bye",若是则聊天结束
if ("bye".equalsIgnoreCase(msg)) {
System.out.println("客户端" + ia + "已下线!");
break;
}
// 实现服务器向客户端回发消息
ps.println("I received!");
//System.out.println("服务器发送数据成功!");
}
// 4.关闭Socket
ps.close();
br.close();
s.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}

客户端:

(1)创建Socket类型的对象并提供服务器的IP地址和端口号;

(2)使用输入输出流通信;

(3)关闭Socket;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
public class ClientStringTest {
public static void main(String[] args) {
try {
// 1.创建Socket类型的对象并提供服务器的IP地址和端口号
Socket s = new Socket("XDL-20170621QCO", 8888);
System.out.println("连接服务器成功!");

// 2.使用输入输出流进行通信
Scanner sc = new Scanner(System.in);
PrintStream ps = new PrintStream(s.getOutputStream());
BufferedReader br = new BufferedReader(
new InputStreamReader(s.getInputStream()));

while(true) {
System.out.println("请输入要发送的内容:");
String str = sc.nextLine();
// 实现客户端向服务器发送字符串内容"在吗?"
//Thread.sleep(20000);
//ps.println("在吗?");
ps.println(str);
System.out.println("客户端发送数据成功!");
// 对客户端向服务器发送的内容进行判断,若是"bye"则聊天结束
if("bye".equalsIgnoreCase(str)) {
System.out.println("聊天结束!");
break;
}
// 实现客户端接收服务器回发的消息
String msg = br.readLine();
//System.out.println("客户端接收到的数据内容是:" + msg);
}

// 3.关闭Socket
br.close();
ps.close();
sc.close();
s.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
  • 注意事项

    客户端Socket与服务器Socket对应,都包括输入,输出流.

    客户端的socket.getInputStream()连接于服务器socket.getOutputStream().

    客户端的socket.getOutputStream()连接于服务器socket.getInputStream().