ä¸ã 网络的概念和功能
网络:将若干台计算机使用物理线路或者无线的线路,连接起来的整体。
分类:网络辐射的范围
局域网:LAN
城域网:MAN
广域网:WAN---www
网络的功能:1:数据共享;2:信息的传输
二、IP地址-域名-端口号
IP地址,在某一个网中,一个唯一的地址的标识。
IP地址的表现形式:IPv4
使用四个字节,32位。每一个字节使用点分符分割。十进制表示。
一个字节的取值范围0-255。
例如:192.168.51.242
IP地址分类
A类: 1.0.0.0 ——126.255.255.255
//第一个字节代表这是A类网络。后面三个字节来代表A类网络中可以容纳的主机的个数。
B类: 128.0.0.0 ——191.255.255.255
C类: 192.0.0.0 ——223.255.255.255
D类、E类。是保留的地址。
外网、公网:可以通过互联网直接访问的IP地址。
内网、私网:企业内部使用的。不能在互联网中直接访问的。理解为局域网。
在IP地址3种主要类型里,各保留了3个区域作为私有地址,其地址范围如下:
A类地址:10.0.0.0~10.255.255.255
B类地址:172.16.0.0~172.31.255.255
C类地址:192.168.0.0~192.168.255.255
特殊IP地址:
127.x.x.x
本地loopback测试地址。
通常情况使用127.0.0.1进行本机的测试。
127.0.0.1
localhost:理解为127.0.0.1 别名。
本机地址:192.168.1.253
0.0.0.0:也可以代表本机的地址。可以代表本机的所有地址。地址的集合,代表了本机所有的地址。
255.255.255.255:
子网广播。在局域网中使用,给当前网段的所有的用户广播消息。
域名:
www.baidu.com ip 地址 对应关系。
域名解析服务器 :将域名转换为ip地址的服务器。DNS
ip地址可以确定访问的主机。
通过端口来确定访问的主机的服务。
端口号:
port:一台主机的不同的服务。
IP地址+端口号:访问的某台主体 提供的服务。
无符号的short类型:0~65535。
0-255:给一些知名的服务提供的:http:80 ftp:21。
256---1023:Unix系统提供的一些服务。
1024-65535:是可以使用的。
1024-5000:使用这个区间的端口号。
端口号,不是物理设备,而是逻辑端口。
三、协议-TCP-UDP
TCP :传输控制协议。 Transfer control protocol
特点:可靠的,安全的,面向连接的,全双工的 字节流协议。
面向连接:信息交互的双方,必须先建立一个供双方单独使用的连接,然后才可以进行信息的交互。类似于打电话:先拨通电话(建立连接的过程),然后再发送语音信息。
全双工:在接收消息的同时可以发送消息。
可靠的,安全的:
1:三次握手(建立连接的过程)
A--->B
1: A 对 B 说: 我可以连接你么?
2:B 回复A 说:好的。
3:A 对 B 说:我现在就连接你。
2:四次挥手(断开连接,保证数据收发无误的过程)
A已经把所有的数据都发送完毕给B。断开连接
1:A 对 B 说:数据发送完毕了,我可以断开连接了吗?
2:B 对 A 回复:你稍等,我看看是否收到了所有的数据。
B 必须保证所有的A的数据都过来了。
3:B 检测所有的数据都接收到了。对A 说: 好了,可以断开连接了。
4:A 收到信息后回复:我现在就断开。
优点:安全可靠。
缺点:会发送一些用于数据校验的信息。造成流量的浪费。 110%。
UDP:User datagram protocol 用户数据报协议。
特点:不安全的,不可靠的,不面向连接的,用户数据报协议。
类似写信:把需要发送的数到放到一个包裹中。然后将发送的目的地写到包裹上,就扔到网络中了。
优点:效率高。
缺点:不安全,数据包大小有限制,最多64K。
四、网络模型-OSI-TCP/IP
OSI参考模式:开放系统互连参考模型(Open System Interconnect)
OSI更多是提供了理论基础。
TCP/IP参考模型:传输控制/网际协议 Transfer Control Protocol/Internet Protocol
实际中使用的是TCP/IP参考模型
五、InetAddress
java.net.* 包下
InetAddress:描述的是 IP 地址+ 主机名(有可能获得不到)
import java.net.InetAddress;
public class InetAddressTest {
public static void main(String[] args) throws Exception{
//得到本机的IP地址+主机名 的 InetAddress对象
InetAddress address = InetAddress.getLocalHost();
System.out.println(address);
//百度服务器的IP 地址 + 主机名
InetAddress address2 = InetAddress.getByName("www.baidu.com");
System.out.println(address2);
//得到所有的能访问到的百度的服务器的主机名+IP地址
InetAddress[] addresses = InetAddress.getAllByName("www.baidu.com");
for (InetAddress inetAddress : addresses) {
System.out.println(inetAddress);
}
}
}
InetSocketAddress: 封装的是 IP地址 + 端口号。
六、URL
URL:https://www.jianshu.com/p/65a71c6f09ca
一个URL 由哪几部分组成?
四部分:
1:协议:http
2:主机的IP地址:域名 www.jianshu.com
3:端口号:默认80端口。
4:被访问的文件 /p/65a71c6f09ca
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
public class URLTest {
public static void main(String[] args) throws Exception{
URL url = new URL("http://sports.qq.com/a/20180613/015325.htm");
System.out.println(url.getProtocol());//得到访问的协议
System.out.println(url.getFile());//访问的文件名称
System.out.println(url.getHost());//访问的主机域名
System.out.println(url.getPort());//端口号,如果不显示写出,-1
//获取服务器反馈的信息
//通过字节流 访问服务器上的信息
InputStream is = url.openStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is,"gb2312"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("c://1.htm")));
String str = br.readLine();
while(str != null){
bw.write(str);
bw.newLine();
str = br.readLine();
}
br.close();
bw.close();
}
}
ä¸ã socket 编程
socket 编程:
套接字编程。
例1:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* 实现:客户端1 给客户端2 发送 一条信息。 客户端2 收到之后,回复一条信息
*
*/
public class UDPClient1 {
public static void main(String[] args) throws Exception {
//创建用于发送数据的socket 对象 系统分配一个可用的端口号用户发送数据。
DatagramSocket ds = new DatagramSocket();
//将发送的数据打包
String str = "多年不见,其实从来没见过,也不知道你现在身在何方,是否还记得我?!";
byte[] buf = str.getBytes();
DatagramPacket dp = new DatagramPacket(buf , buf.length, InetAddress.getByName("192.168.51.242"), UDPClient2.PORT);
//发送数据包
ds.send(dp);
//接收 另外一段的反馈
buf = new byte[1024];
dp = new DatagramPacket(buf, buf.length);
ds.receive(dp);
//解析dp
ObjectInputStream ois =new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(buf)));
System.out.println(ois.readObject());
ois.close();
//关闭ds
ds.close();
}
}
class UDPClient2{
//本地接收的端口号
public static final int PORT = 1777;
public static void main(String[] args) throws Exception{
//创建接收信息的socket 并指明使用本地的哪个端口接收信息
DatagramSocket ds = new DatagramSocket(PORT);
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//接收数据 阻塞式方法。没有数据包就等待
ds.receive(dp);
//解析dp 的原始数据
int len = dp.getLength();
String str = new String(buf,0,len);
System.out.println("杨树发来的信息为:"+str + dp.getAddress() );
//回复一条 回复一个对象 如何将一个对象转换为字节数组
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(baos);
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(new GirlFriend("徐小蕾", 20, 100));
oos.flush();
buf = baos.toByteArray();
//将buf 封装到一个 DatagramPacket 对象中。然后使用ds 发送回去。
dp = new DatagramPacket(buf, buf.length, dp.getAddress(), dp.getPort());
ds.send(dp);
oos.close();
ds.close();
}
}
class GirlFriend implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private int age;
private int eq;
GirlFriend(String name, int age, int eq) {
super();
this.name = name;
this.age = age;
this.eq = eq;
}
@Override
public String toString() {
return "GirlFrided [name=" + name + ", age=" + age + ", eq=" + eq + "]";
}
}
例2:UDP-chat
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* 聊天室:
* 功能:
* 1:给指定的人发送信息:指定对方的IP地址
* 2:给所有的人发送信息:使用广播地址
* 接收键盘的输入 new BufferedReader(new InputStreamReader(System.in));
* readLine()//阻塞方法
* 使用一个单独的发送的线程。
*
* 3:接收信息
* //阻塞方法
* receive(dp)
* 使用一个单独的接收的线程。
*
*/
public class UDPChatClient {
public static final int PORT = 1777;
public static void main(String[] args) throws SocketException {
DatagramSocket ds = new DatagramSocket(PORT);
new SendThread(ds).start();
new ReceiveThread(ds).start();
}
//发送线程的内部类
static class SendThread extends Thread{
private DatagramSocket ds;
public SendThread(DatagramSocket ds) {
this.ds = ds;
}
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length, null, PORT);
//接收键盘输入,并将输入的内容发送给指定的人。指定IP
while(true){
//先输入对方的IP地址
System.out.println("请输入对方的IP地址:");
String ip = br.readLine();
//在输入发送的内容
System.out.println("请输入发送的内容:");
String msg = br.readLine();
//将输入的内容转换为字节数据
buf = msg.getBytes();
InetAddress address = InetAddress.getByName(ip);
//
dp.setAddress(address);
dp.setData(buf);
dp.setLength(buf.length);
ds.send(dp);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//接收信息的线程的内部类
static class ReceiveThread extends Thread{
private DatagramSocket ds;
public ReceiveThread(DatagramSocket ds) {
this.ds = ds;
}
public void run() {
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
try {
while(true){
ds.receive(dp);
//解析dp
String str = new String(buf,0,dp.getLength());
System.out.println(dp.getAddress() + " --> " + str);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
例3:UDP-chat-GUI
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Label;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* 聊天室:
* 功能:
* 1:给指定的人发送信息:指定对方的IP地址
* 2:给所有的人发送信息:使用广播地址
* 接收键盘的输入 new BufferedReader(new InputStreamReader(System.in));
* readLine()//阻塞方法
* 使用一个单独的发送的线程。
*
* 3:接收信息
* //阻塞方法
* receive(dp)
* 使用一个单独的接收的线程。
*
*/
public class UDPChatRoom {
public static final int PORT = 1777;
//窗口大小
public static final int FRAME_WIDTH = 600;
public static final int FRAME_HEIGHT = 500;
//屏幕的宽高
public static final int SYS_SCREEN_W = java.awt.Toolkit.getDefaultToolkit().getScreenSize().width;
public static final int SYS_SCREEN_H = java.awt.Toolkit.getDefaultToolkit().getScreenSize().height;
//窗口的所有的组件
static TextArea area;//多行,多列
static Label ipLabel;
static Label msgLabel;
static TextField ipField;
static TextField msgField;
static Button sendBtn;
public static void main(String[] args) throws SocketException {
DatagramSocket ds = new DatagramSocket(PORT);
initChatWindow(ds);
// new SendThread(ds).start();
new ReceiveThread(ds).start();
}
/**
* 初始化聊天窗口
*/
private static void initChatWindow(DatagramSocket ds){
//创建一个Frame 窗口,并指定标题名称, 需要将窗口 设置为显式状态
Frame frame = new Frame("501聊天室");
//设置窗口大小
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
//设置窗口的起始位置
frame.setLocation(SYS_SCREEN_W-FRAME_WIDTH>>1, SYS_SCREEN_H-FRAME_HEIGHT>>1);
//设置窗口大小不可变
frame.setResizable(false);
//设置frame 的窗口组件的布局格式
frame.setLayout(new FlowLayout());
//初始化frame 组件
initFrameComponent(frame, ds);
//添加窗口关闭事件
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
/**
* 初始化frame 的组件
*/
private static void initFrameComponent(Frame frame , DatagramSocket ds){
area = new TextArea(24, 80);
area.setEditable(false);
frame.add(area);
ipLabel = new Label("对方IP地址:");
frame.add(ipLabel);
ipField = new TextField(66);
frame.add(ipField);
msgLabel = new Label("发送的内容:");
frame.add(msgLabel);
msgField = new TextField(66);
frame.add(msgField);
sendBtn = new Button("发送");
//给button 添加 按下的事件
sendBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//当按钮被按下的时候,会被调用
//获得文本框中的内容
String ip = ipField.getText();
String msg = msgField.getText();
msgField.setText("");//清空文本框
try {
InetAddress address = InetAddress.getByName(ip);
byte[] buf = msg.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, address, PORT);
ds.send(dp);
//将发送的内容添加到文本域中。
area.append("我 --> "+msg +"\r\n");
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
frame.add(sendBtn);
}
//接收信息的线程的内部类
static class ReceiveThread extends Thread{
private DatagramSocket ds;
public ReceiveThread(DatagramSocket ds) {
this.ds = ds;
}
public void run() {
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
try {
while(true){
ds.receive(dp);
//解析dp
String str = new String(buf,0,dp.getLength());
// System.out.println(dp.getAddress() + " --> " + str);
area.append(dp.getAddress() + " --> " + str +"\r\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}