网络编程补充
IP地址
IP地址是指互联网协议地址(更多的时候是互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异)
ip地址一般是由32位二进制组成,已知ip地址是分为四段,所以又32/4=8位,所以每一段的取值个数是2^8=256个(包括0)
但是在二进制里面,是包括0的,所以每一段取值为0-255这个值。
分为a b c d e 五类
a 0+7位网络号 (紫色)+主机号(绿色部分) 1.0.0.0 到 127.255.255.255 之间
b 10+14位网络号 +主机号 127.0.0.0 到191.255.255.255之间
c 110+21位网络号 +主机号 192.0.0.0 到 223.255.255.255
d 1110+多点播送地址 224.0.0.0 到 239.255.255.255
e 11110+留做将来使用 240.0.0.0+ 247.255.255.255
网络号在分配给商家的时候,是固定的,后面的主机号是可变的。
a地址表示开头第一段的值,因为最大是7位,而且不包括0,所以取值为1-127,后面的三段地址都可以获取0-255值。
那么a地址,后面三段都是可变的地址,而开头一段是固定在某个范围内,所以a地址就有127个这种地址,不算后面可变的。那么其分配给主机的时候,那么就是127 *255 * 255 *255
注意商家在得到一个地址的时候,因为第一段地址的固定的,所以对于商家来说,a类地址很珍贵。因为可变的部分是作为你可以分配的主机
所以一个a类地址拥有的主机数量有: (0-255包括0,所以)256 * 256 * 256个地址
目前普遍使用最多的是c类地址。目前公司内部就是使用C类地址
本地回路地址
127.0.0.1——这地址只能作为自己的一个本地回路地址,不能作为网络上的一个ip地址
计算机中正确安装TCP/IP协议后,计算机中都会有一个称做本地回路的地址 发往 127.0.0.1 的数据不经过网卡传递,
而是指接被本地计算机中Tcp/ip协议栈中的几个上层协议接收,是一个用于本地计算机上使用的特殊地址,使用Ping
就可以检查TCP/IP协议是否正确安装,它没有和网卡绑定,网卡没有正确连接或是没有网线的情况下,仍可使用该地址
端口
因为一个计算机上同时可运行多个网络程序,而IP地址只能保证把数据送到某个计算机上,但不能保证把数据交给计算机上的每个程序,因此每个发送的网络数据包的头部,都包含有一个称为端口号的整数
系统保留的端口有1-1023,这些不能使用
网络协议
规定了计算机之间连接的物在机械,电器等特性,及计算机间的相互寻址规则,和以数据发送冲突的解决办法,分段传输与解决大数据包的传输方式等等
简单理解为:因为互联网出来之后,为了能够清楚数据之间的交互,让数据的传输有规章(例如:你在中国,说中文才让人容易懂你讲了什么。去外国,你说中文老外不知道,但是说英语可以明白你想要干嘛什么。)
. HTTP1.1(Hypertext Transfer Protocol Vertion 1.1)超文本传输协议-版本1.1
. ARP(Address Resolution Protocol)地址解析协议
. SNMP(Simple Network Management Protocol)网络管理协议
. CMIP(Common Management Information Protocol)通用管理信息协议
. DHCP(Dynamic Host Configuration Protocol)动态主机配置协议
. FTP(File Transfer Protocol)文件传输协议
. IPv6(Internet Protocol Version 6)Internet协议-版本6
. IPX/SPX(Internetwork Packet Exchange/Sequential PacketExchange)互连网包交换/顺序包交换
. POP3(Post Office Protocol Version 3)邮局协议-版本3
. PPP(Point to Point Protocol)点对点协议
. SMTP(Simple Mail Transfer Protocol)简单邮件传送协议
. TELNET Protocol虚拟终端协议
. UDP(User Datagram Protocol)用户数据报协议
目前不用记住网络协议。大概明白协议的作用,明白在互联网的数据传输需要些什么。
OSI参考模型 (iso是国际标准化组织)
OSI参考模型 (Open System Interconnect 开放式网络互联) // TCP/IP参考模型
七层:
应用层 Application 一些终端应用
表示层 Presentation 对接收的数据进行解释,加密和解密(把计算机能识别的东西.转换成人能识别的东西)如图片声音等
会话层 Session 建立数据传输通路
传输层 Transport 定义了一些数据传输的协议和端口号 常把这一层的数据叫段 //网关
网络层 Transport 将从下层接收到的数据进行IP地址的封装和解装 在这一层工作的设备叫路由器, 常把这层的数据叫包
数据链路层 Data Link 将从物理层接收的数据进行MAC(网卡地址)的封装和解装,常把这一层的数据叫帧 在这一层工作的设备叫交换机,网卡,网桥
物理层 Physical,这一层的数据叫比特 //光纤
TCP/IP分层模型(TCP/IP Layening Model)被称作因特网分层模型(Internet Layering Model)、因特网参考模型(Internet Reference Model)。简化了OSI模型
第四层,应用层(会话层、表示层、应用层)
第三层,传输层(传输层)
第二层,网间层(网络层 )
第一层,网络接口层(物理层、数据链路层)
UDP/TCP
与上面的介绍的TCP不是用一个概念,上面的在分层模型上概念上介绍
TCP (Transmission Control Protocol )
传输控制协议,是面向连接的通信协议,提供两台计算机之间的可靠和无差错的数据传输,数据源和目标之间或建立一个虚拟的连接,建立后,计算机之间就会把数据,当作双向字节流进行交换
三次握手
- 客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
- 服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。
- 客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。
简单理解就是:
我与老王准备发送数据,首先老王在准备了(服务器被动打开)。
我先问老王“我可以和你连接了吗?”——第一次握手
老王反馈说“可以”——第二次握手
我再对老王说“那我开始咯”——第三次握手
最终创建连接
UDP
用户数据报协议,(USER datagram Protocol) 是无连接的通信协议,不保证数据的可靠传输,能够向若干个目标发送和接收数据,数据包会有丢失\的时候
简单理解就是:
我发送数据给老王,我不问老王在不在,直接发送数据
TCP、UDP 数据包的帧格式
TCP与UDP传输数据的过程中,大概知道下他们传输的内容(不做重点,因为io流会我们实现)
协议类型 源IP 目标IP 源端口 目标端口 帧序号 帧数据
协议类型用来区分 用的是哪个协议,是UDP 还是TCP
套接字 Socket 简介
网络驱动程序提供给应用程序编程的接口和一种机制
可以比喻成一个港口码头 应用程序只要把货放在这,就算完成了货物的运送
它在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自已对应的IP 和 Port
java中用于网络通讯的包是 java.net 包
Socket //用于TCP通讯的客户端
ServerSocket //用于TCP通讯的服务端
DatagramSocket //用于UDP 通讯
TCP Socket 开发步骤
服务端代码
public class SocketSever {
public static void main(String[] args) {
try {
// 1.创建一个ServerSocket对象 传入连接端口
ServerSocket serverSocket = new ServerSocket(5500);
System.out.println("服务端启动,等待连接......");
/*
* 2.调用ServerSocket对象的accept()方法接受客户端请求(建立连接)得到一个Socket对象——第一次握手接收方
* 因为这里的服务端在等待客户端的连接,所以线程会阻塞,直到有客户端和这边连接为止,会一直等待下去
*/
Socket socket = serverSocket.accept();
System.out.println("与客户端连接成功...");
/*
* 3.获取Socket对象的输入输出流
* 因为这边预定会穿字符串,所以可是使用InputStreamReader将字节流转为字符流
* 再利用BufferedReader这个缓冲流
* */
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
/*
* 4.读取客户端传过来的数据读取
* readLine 方法直接将客户端传输过来的数字转为字符串,打印结果
* */
String content = br.readLine();
System.out.println("服务器接收到:"+content);
//5.关闭流
br.close();
//6.关闭连接
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端
public class SocketClient {
public static void main(String[] args) {
try {
System.out.println("客户端准备连接服务端......");
/*
* 1.创建一个Socket对象,传入想要连接的ip地址和端口 相当于建立了连接,也就是说三次握手在执行完这个步骤的就完成了
*/
Socket socket = new Socket("127.0.0.1", 5500);
System.out.println("与服务端完成连接");
// 2.通过Socket对象获取输出流,因为打算传字符串,所以还是转为字符流
OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
// 使用缓冲流
BufferedWriter bufferedWriter = new BufferedWriter(writer);
// 3.输出内容
bufferedWriter.write("我是客户端.");
// 4.关闭流
bufferedWriter.flush();// 记得刷新
bufferedWriter.close();
// 5.断开连接
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
练习:利用TCP连接,服务端多线程处理,可以接收多个客户端的连接
Class2:hServer:
package day18.com.test.class2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务器传信息给客户端
public class HomeworkServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
try {
// 服务器
// 1.创建一个ServerSocket对象
serverSocket = new ServerSocket(8088);// 指定的端口
System.out.println("服务端等待连接...");
// 2.调用accept()方法接受客户端请求(建立连接)
socket = serverSocket.accept();
// 3.获取socket对象的输入输出流
inputStream = socket.getInputStream();
// 4.读取客户端传过来的数据
int i = 0;
byte[] bs = new byte[1024];
while ((i = inputStream.read(bs)) != -1) {
// System.out.println(new String(bs, 0, i));
String mString = new String(bs, 0, i);
System.out.println(mString);
if ("over".equals(mString)) {
break;
}
}
// // 第二步,服务端回复信息给客户端//输出信息,就是用outputStream
outputStream = socket.getOutputStream();
outputStream.write("好的!我已经收到了你的信息。".getBytes());
} catch (IOException e) {
// TODO: handle exception
} finally {
try {
// 5.关闭流
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
// 6.关闭连接
if (serverSocket != null) {
serverSocket.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e2) {
// TODO: handle exception
}
}
}
}
Class2:hClient:
package day18.com.test.class2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class HomeworkClient {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream = null;
InputStream inputStream = null;
try {
// 客户端
// 1.创建一个Socket对象(相当于建立了连接)
socket = new Socket("127.0.0.1", 8088);
System.out.println("111");
// 2.获取输出流
outputStream = socket.getOutputStream();
// 3.输出内容
outputStream.write("你好,我是Client \r\n".getBytes());
while (true) {
System.out.println("请输入你要发送的信息:");
Scanner scanner = new Scanner(System.in);
String mString = scanner.nextLine();
outputStream.write(mString.getBytes());
// 发起指定让服务端停止读取信息//自己定义一个指令”over"
if ("over".equals(mString)) {
break;
}
}
// 读取服务端回复的信息
inputStream = socket.getInputStream();
byte[] b = new byte[1024];
int i = 0;
while ((i = inputStream.read(b)) != -1) {
System.out.println(new String(b, 0, i));
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
// 4.关闭流
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
if (inputStream != null) {
inputStream.close();
}
// 5.断开连接
if (socket != null) {
socket.close();
}
} catch (IOException e2) {
// TODO: handle exception
}
}
}
}
Class3:hServer:
package day18.com.test.class3;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务器传信息给客户端
public class HomeworkServer {
public static void main(String[] args) {
// BufferInputStream 和Output也是一个资源,所以我们要关闭资源
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
try {
// 服务器
// 1.创建一个ServerSocket对象
serverSocket = new ServerSocket(8088);// 指定的端口
System.out.println("服务端等待连接...");
// 2.调用accept()方法接受客户端请求(建立连接)
socket = serverSocket.accept();
// 3.获取socket对象的输入输出流
inputStream = socket.getInputStream();
// 想要使用上Buffer'e'd'InputStream
bufferedInputStream = new BufferedInputStream(inputStream);
// 4.读取客户端传过来的数据
int i = 0;
byte[] bs = new byte[1024];
while ((i = bufferedInputStream.read(bs)) != -1) {// 有一个等待的情况
// System.out.println(new String(bs, 0, i));
String mString = new String(bs, 0, i);
System.out.println(mString);
if ("over".equals(mString)) {
break;
}
}
// // 第二步,服务端回复信息给客户端//输出信息,就是用outputStream
outputStream = socket.getOutputStream();
// 带缓冲的输出流 这样的写法,就是之前学到的io流中的bufferedOutStream的写法
bufferedOutputStream = new BufferedOutputStream(outputStream);
bufferedOutputStream.write("好的!我已经收到了你的信息。".getBytes());
bufferedOutputStream.flush();
} catch (IOException e) {
// TODO: handle exception
} finally {
try {
//要先关闭buffered outputStream
if (bufferedOutputStream != null) {
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
// 5.关闭流
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
// 6.关闭连接
if (serverSocket != null) {
serverSocket.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e2) {
// TODO: handle exception
}
}
}
}
Class3:hClient:
package day18.com.test.class3;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class HomeworkClient {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream = null;
InputStream inputStream = null;
BufferedOutputStream bufferedOutputStream = null;
BufferedInputStream bufferedInputStream = null;
try {
// 客户端
// 1.创建一个Socket对象(相当于建立了连接)
socket = new Socket("127.0.0.1", 8088);
System.out.println("111");
// 2.获取输出流
outputStream = socket.getOutputStream();
bufferedOutputStream = new BufferedOutputStream(outputStream);
// 3.输出内容
bufferedOutputStream.write("你好,我是Client \r\n".getBytes());
while (true) {
System.out.println("请输入你要发送的信息:");
Scanner scanner = new Scanner(System.in);
String mString = scanner.nextLine();
bufferedOutputStream.write(mString.getBytes());
bufferedOutputStream.flush();
// 发起指定让服务端停止读取信息//自己定义一个指令”over"
if ("over".equals(mString)) {
break;
}
}
// 读取服务端回复的信息
inputStream = socket.getInputStream();
bufferedInputStream = new BufferedInputStream(inputStream);
byte[] b = new byte[1024];
int i = 0;
while ((i = bufferedInputStream.read(b)) != -1) {
System.out.println(new String(b, 0, i));
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
// 4.关闭流
if (bufferedOutputStream != null) {
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
if (inputStream != null) {
inputStream.close();
}
// 5.断开连接
if (socket != null) {
socket.close();
}
} catch (IOException e2) {
// TODO: handle exception
}
}
}
}
Class4:hServer:
package day18.com.test.classx3;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务器传信息给客户端
public class HomeworkServer {
public static void main(String[] args) {
// BufferInputStream 和Output也是一个资源,所以我们要关闭资源
try {
// 服务器
// 1.创建一个ServerSocket对象
ServerSocket serverSocket = new ServerSocket(8088);// 指定的端口
System.out.println("服务端等待连接...");
// 等待多个客户连接,就是用循环连接
while (true) {// 死循环
// 2.调用accept()方法接受客户端请求(建立连接)
Socket socket = serverSocket.accept();
// 创建一个子线程
new Thread(new Runnable() {// 使用了匿名内部类
@Override
public void run() {
// TODO Auto-generated method stub
// 3.获取socket对象的输入输出流
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = socket.getInputStream();
// 想要使用上Buffer'e'd'InputStream
bufferedInputStream = new BufferedInputStream(inputStream);
// 4.读取客户端传过来的数据
int i = 0;
byte[] bs = new byte[1024];
while ((i = bufferedInputStream.read(bs)) != -1) {// 有一个等待的情况
String mString = new String(bs, 0, i);
System.out.println(mString);
if ("over".equals(mString)) {
break;
}
}
// 第二步,服务端回复信息给客户端//输出信息,就是用outputStream
outputStream = socket.getOutputStream();
// 带缓冲的输出流 这样的写法,就是之前学到的io流中的bufferedOutStream的写法
bufferedOutputStream = new BufferedOutputStream(outputStream);
bufferedOutputStream.write("好的!我已经收到了你的信息。".getBytes());
bufferedOutputStream.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
// 要先关闭buffered outputStream
if (bufferedOutputStream != null) {
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
// 5.关闭流
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
// 6.关闭连接
if (serverSocket != null) {
serverSocket.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e2) {
// TODO: handle exception
}
}
}
}).start();
}
} catch (IOException e) {
// TODO: handle exception
} finally {
}
}
}
Class4:hClient:
package day18.com.test.classx3;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class HomeworkClient {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream = null;
InputStream inputStream = null;
BufferedOutputStream bufferedOutputStream = null;
BufferedInputStream bufferedInputStream = null;
try {
// 客户端
// 1.创建一个Socket对象(相当于建立了连接)
socket = new Socket("127.0.0.1", 8088);
System.out.println("111");
// 2.获取输出流
outputStream = socket.getOutputStream();
bufferedOutputStream = new BufferedOutputStream(outputStream);
// 3.输出内容
bufferedOutputStream.write("你好,我是Client \r\n".getBytes());
while (true) {
System.out.println("请输入你要发送的信息:");
Scanner scanner = new Scanner(System.in);
String mString = scanner.nextLine();
bufferedOutputStream.write(mString.getBytes());
bufferedOutputStream.flush();
// 发起指定让服务端停止读取信息//自己定义一个指令”over"
if ("over".equals(mString)) {
break;
}
}
// 读取服务端回复的信息
inputStream = socket.getInputStream();
bufferedInputStream = new BufferedInputStream(inputStream);
byte[] b = new byte[1024];
int i = 0;
while ((i = bufferedInputStream.read(b)) != -1) {
System.out.println(new String(b, 0, i));
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
// 4.关闭流
if (bufferedOutputStream != null) {
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
if (inputStream != null) {
inputStream.close();
}
// 5.断开连接
if (socket != null) {
socket.close();
}
} catch (IOException e2) {
// TODO: handle exception
}
}
}
}
给飞秋发送消息
package day18.com.test.class4;
//给飞秋发送消息
import java.io.*;
import java.net.*;
public class Test {
public static void main(String[] args) throws IOException {
String[] strings = { "你不是孤单一个人。", "希望和奇迹是存在的。",
"今天也要打起精神来。",
"恋爱可是门高深莫测的学问哟。",
"赶快胜利,接下来就是两个人的时间喽。",
"恋爱和战斗都要勇往直前。"
,
"花会枯萎,爱永不凋零。"
,
"小乔,要努力变强。"
,
"觉醒吧,猎杀时刻"
,
"周日被我射熄火了,所以今天是周一"
,
"走,最后的太阳"
,
"要变天了"
,
"光明制造黑暗"
,
"我的猎场"
,
"最光明,最黑暗"
,
"别了,太阳"
,
"发光的,一个就够了"
,
"hello 你好啊"
};
// 飞秋的数据格式
// 发送的管道
DatagramSocket ds = new DatagramSocket();// upd类型
// 数据包
// ds.send(dp);
int i = 0;
while (i < 50) {
String str = "1:100:Jason:二十年后的你:32:" + strings[(int) (Math.random() * (strings.length))];
byte[] array = str.getBytes();
DatagramPacket dp = new DatagramPacket(array, array.length, InetAddress.getByName("192.168.29.1"), 2425);
ds.send(dp);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
}