一、概念
1. 计算机网络:计算机+外围设备+链路-》分享资源和信息处理等
2. 网络通信协议:不同的计算机不同的底层结构,网络通信协议相当于一系列标准,就像来自不同官方语言国家的两个人可以采用同一种语言进行沟通
3. 网络通信接口:
- 硬件装置,实现节点之间的信息传递,如网卡
- 软件装置,规定双方进行通信的约定协议
4. 分层:互不影响,灵活,利于拓展和实现
5. OSI参考模型 VS TCP/IP参考模型
01010...->帧frame->包packet->segment
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
6. IP是网际层的主要协议:
- 提供独一无二的IP地址
- 无连接数据报传送
- 数据报路由选择和差错控制
- 网络地址+主机地址(使用子网掩码来划分,如255.255.255.0)
**1
IP地址分类 | 第一字节范围 | 固定最高位 | 网络位 | 网络数 | 主机位 | 主机数 |
A | 0~127 | 0 | 8 | 126 (0和127特殊用途) | 16777214 (2^24 - 2) | |
B | 128~191 | 10 | 16 | 2^14 | 16 | 2^16 -2 |
C | 192~223 | 110 | 24 | 2^21 | 8 | 2^8 -2 |
D | 224~239 | 1110 | 组播地址 | |||
E | 240~255 | 11110 | 保留给实验用 |
特殊地址 | 网络id | 主机id | 源地址使用 | 目的地址使用 | 备注 |
本网络的本台主机 | 全0 | 全0 | 可以 | 不可以 | 运行引导程序时,但又不知道其ip, 则使用这个 |
本网络的某台主机 | 全0 | 主机id | 不可以 | 可以 | |
网络地址 | 网络id | 全0 | 可以 | 可以 | |
直接广播地址 | 网络id | 全1 | 不可以 | 可以 | 特定网络所有主机,即全网广播 |
受限/本地 广播地址 | 全1 | 全1 | 不可以 | 可以 | |
回送地址 | 127 | 任何数 | 可以 | 可以 |
7. NAT:共享互联网,私网使用的是保留地址,而连接外网的接口使用的是非保留IP地址
- 私网IP
类型 | 网络地址 | 网络数 |
A | 10.x.x.x | 1 |
B | 172.16.x.x ~ 172.31.x.x | 16 |
C | 192.168.x.x ~ 192.168.x.x | 256 |
8. 网关gateway:内网,外围,两块内存
9. 广播:
- 直接广播,网络ID+主机ID(全1),像某个网段广播信息
- 本地广播,网络ID(全是1)+主机ID(全是1),像本地网段广播信息
10. 组播:广播给一组计算机
11. 划分子网例子:
http://blog.chinaunix.net/uid-20788636-id-1841323.html
12. TCP VS UDP:
TCP提供可靠地(但是慢,时效低),端到端的字节流通信的协议,是一种面向连接的协议,TCP连接是字节流而非报文,采用3次握手和重传(时间,重传次数,重复)
- A请求连接-》B
- A《- B接受请求,准备接收
- A -》B发送数据
- A《- B确认
UDP提供了一种发送封装的原始IP数据报的方法,发送之前不需建立连接,因此这是个不可靠的连接(但是速度快)
二、实现
java.net.Socket(插座):
双向的网络通信实现数据的交换,这个双向链路的一端称为socket,分别用来实现双向连接的client和server,建立连接时所需的寻址信息为远程计算机IP地址和端口号port number(TCP和UDP各有6万多个,一个应用程序可以有多个端口号,1024以下不要用,因为系统可能已经占用了)。对于UDP没有严格的client和server概念。
注意要先启动Server再启动Client,因为Server一般是不断的提供服务(同时打开多次同一个server是不可以的,accept方法是一个循环之后再执行另一个循环),所以我们可以while(true) {s.accept();},多个client可以同时申请连接,但是由服务器决定接收哪个连接。
- socket.getInetAddress() //获取客户端地址(超集,不一定是IP地址)
- socket.getPort()
import java.net.*;
import java.io.*;
public class TestUDPServer
{
public static void main(String args[]) throws Exception
{
byte buf[] = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
DatagramSocket ds = new DatagramSocket(5678);
while(true)
{
ds.receive(dp);
ByteArrayInputStream bais = new ByteArrayInputStream(buf);
DataInputStream dis = new DataInputStream(bais);
System.out.println(dis.readLong());
}
}
}
import java.net.*;
import java.io.*;
public class TestUDPClient
{
public static void main(String args[]) throws Exception
{
long n = 10000L;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeLong(n);
byte[] buf = baos.toByteArray();
System.out.println(buf.length);
DatagramPacket dp = new DatagramPacket(buf, buf.length,
new InetSocketAddress("127.0.0.1", 5678)
);
DatagramSocket ds = new DatagramSocket(9999);
ds.send(dp);
ds.close();
}
}
多客户端Knock Knock游戏:
import java.net.*;
import java.io.*;
public class KKThread extends Thread{
Socket s = null;
KKThread(Socket s) {
super("MultiServerThread");
this.s = s;
}
public void run() {
try(BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream()))) {
KKState kks = new KKState();
String input, output;
output = kks.processInput(null);
pw.println(output);
pw.flush();
while((input = br.readLine()) != null) {
output = kks.processInput(input);
pw.println(output);
pw.flush();
if(output.equals("Bye"))
break;
}
br.close();
pw.close();
s.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
public class KKState {
private static final int WAITING = 0;
private static final int SENTKNOCK = 1;
private static final int SENTCLUE = 2;
private static final int ANOTHER = 3;
private static final int NUMOFJOKES = 5;
private int current = 0;
private int state = WAITING;
private final String[] clues = {"Turnip", "Little Old Lady", "Atch", "Who", "Who"};
private final String[] ans = {"Turnip the heat, It's cold in there.", "I didn't know you could yodel.", "Bless you.", "Is there an owl in there.", "Is there an echo in there."};
String processInput(String input) {
String output = null;
if(state == WAITING) {
output = "Knock Knock";
state = SENTKNOCK;
} else if(state == SENTKNOCK) {
if(input.equalsIgnoreCase("Who's there?")) {
output = clues[current];
state = SENTCLUE;
} else {
output = "You are supposed to say \"Who's there?\"!Try again. Knock Knock";
}
}
else if(state == SENTCLUE) {
if(input.equalsIgnoreCase(clues[current]+" who?")) {
output = ans[current] + " Want another[y/n]";
state = ANOTHER;
} else {
output = "You are supposed to say \""+clues[current]+" who?\"!Try again. Knock Knock";
state = SENTKNOCK;
}
}
else if(state == ANOTHER) {
if(input.equalsIgnoreCase("y")) {
output = "KNOCK KNOCK";
if(current == (NUMOFJOKES - 1)) {
current = 0;
} else
current++;
state = SENTKNOCK;
} else {
output = "Bye";
state = WAITING;
}
}
return output;
}
}
import java.net.*;
import java.io.*;
public class KnokServer {
public static void main(String[] args) {
try(ServerSocket ss = new ServerSocket(9998)) {
System.out.println("Server started");
while(true) {
Socket cs = null;
try {
cs = ss.accept();
} catch(IOException e) {
System.out.println("Accept failed: " + 9998 + "," +e.getMessage());
continue;
}
new KKThread(cs).start();
}
} catch(IOException e) {
System.err.println("Could not listen on port: " + 9998 + "," + e.getMessage());
}
}
}
import java.net.*;
import java.io.*;
public class KKClient {
public static void main(String[] args) {
try(Socket cs = new Socket("127.0.0.1", 9998)) {
try {
PrintWriter pw = new PrintWriter(new OutputStreamWriter(cs.getOutputStream()));
BufferedReader br = new BufferedReader(new InputStreamReader(cs.getInputStream()));
String input, output;
try {
while((input = br.readLine()) != null) {
System.out.println("Server: " + input);
if(input.equals("Bye")) {
break;
}
BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
output = sin.readLine();
System.out.println("Client: " + output);
pw.println(output);
pw.flush();
}
} catch(IOException e) {
System.err.println("Unable to open I/0 streams " + e);
}
pw.close();
br.close();
} catch(IOException e) {
System.err.println("Unable to open socket to Host " + e);
}
cs.close();
} catch(IOException e) {
System.err.println("Unable to connect the host" + e);
}
}
}
Reference:
1. http://blog.csdn.net/youxin2012/article/details/25778255