目录
网络编程
两种软件架构
网络通信的三要素
IP
IPv4的地址分类
特殊IP
端口号
协议
用UDP协议发送数据
用UDP接收数据
TCP接收和发送数据
TCP通信--支持与多个客户端同时通信
可以让设备中的程序与网络上其他设备的程序进行数据交互(实现网络通信)
CS:在用户本地需要下载并安装客户端程序,在远程有一个服务器端程序
BS:只需要一个浏览器,用户通过不同的网址,客户访问不同的服务器
设备在网络中的地址,是唯一的标识
有IPv4和IPv6
最多有2^32次方的ip,目前用完了
IPv4中不够用,就有了IPv6
为了解决ipv4不够用而出现的,最多有2^128次方的ip
公网地址(万维网使用)和私有地址(局域网使用)
192.168.开头的就是私有地址,范围即为192.168.0.0--192.168.255.255,专门为组织机构内部使用,以此节约IP
127.0.0.1,也可以是localhost:是回送地址也称本地回环地址,也成为本机IP,永远只会寻找当前所在的本机
常用的CMD命令
ipconfig:查看本机IP地址
ping:检查网络是否连通
public class ip {
public static void main(String[] args) throws UnknownHostException {
// 1.获取InetAddress的对象
// IP的对象 一台电脑对象
InetAddress address = InetAddress.getByName("192.168.135.1");
System.out.println(address);
String name = address.getHostName();
System.out.println(name);
String ip = address.getHostAddress();
System.out.println(ip);
}
}
应用程序在设备中唯一的标识
端口号: 由两个字节表示的整数,取值范围:0-665535,其中0-1023之间的端口用于一些知名的网络服务或应用,我们自己使用1024以上的端口就可以了
数据在网路中传输的规则
UDP协议: 用户数据报协议
UDP是面向无连接通信协议
速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据
TCP协议:传输控制协议
TCP协议是面向连接的通信协议
速度慢,没有大小限制,数据安全
下面是用UDP来发收数据
public class ip {
public static void main(String[] args) throws IOException {
// 发送数据
// 1.创建DatagramSocket对象
// 细节:
//绑定端口,以后我们就是通过这个端口往外发送
//有参:指定端口号进行绑定
DatagramSocket ds = new DatagramSocket();
// 打包数据
String str = "hello world";
byte[] bytes = str.getBytes(); // 将str转换成字节数组来用来打包数据
InetAddress address = InetAddress.getByName("127.0.0.1"); // 表示那台ip电脑来接受
int port=10086; //被发数据电脑接收的端口
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
// 3. 发送数据
ds.send(dp);
// 4.释放资源
ds.close();
}
}
public class receive {
public static void main(String[] args) throws IOException {
// 接收数据
// 1.创建DatagramSocket对象//我们可以做一个比喻: 这就是一个快递公司
// 细节:
// 接收和传输不一样:接收一定要绑定接口
// 而且绑定的端口,一定要跟发送的端口保持一致
DatagramSocket ds = new DatagramSocket(10086);
// 2. 接收数据包
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
ds.receive(dp);
// 3.解析数据包
byte[] data = dp.getData();
int len = dp.getLength();
InetAddress address = dp.getAddress();
int port = dp.getPort();
System.out.println("接收到数据" + new String(data,len));
System.out.println("该数据是从"+address+"接口是"+port);
// .释放资源
ds.close();
}
}
通信双方事先会采用"三次握手"方式建立可靠连接,实现端到端的通信;底层能保证数据成功传到服务端
一发一收
创建客户端
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class Tcp {
public static void main(String[] args) throws IOException {
// 1.创建Socket对象,并同时请求与服务器程序的连接
Socket socket = new Socket("127.0.0.1",8888);
// 2.从socket通信管道中得到一个字节输出流,用来发数据给服务端程序
OutputStream os = socket.getOutputStream();
// 3.把低级的字节输出流包装成数据流
DataOutputStream dos = new DataOutputStream(os);
//4.开始写数据出去了
dos.writeUTF("在一起,好吗?");
dos.close();
socket.close();
}
}
创建服务器
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Res {
public static void main(String[] args) throws IOException {
System.out.println("------服务端启动成功------");
// 1.创建ServerSocket的对象,同时为服务端注册端口
ServerSocket serverSocket = new ServerSocket(8888);
// 2.使用serverSocket对象,调用一个accept方法,等待客户端的连接请求
Socket socket = serverSocket.accept();
// 3. 从socket通信管道中得到一个字节输入流
InputStream is = socket.getInputStream();
//4.把原始的字节输入流包装成数据输入流
DataInputStream dis = new DataInputStream(is);
//5.使用数据输入流读取客户端发送的消息
String rs = dis.readUTF();
System.out.println(rs);
// 其实我们也可以获取客户端的IP地址
System.out.println(socket.getRemoteSocketAddress());
dis.close();
socket.close();
}
}
多发多收
发送数据
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Tcp {
public static void main(String[] args) throws IOException {
// 1.创建Socket对象,并同时请求与服务器程序的连接
Socket socket = new Socket("127.0.0.1",8888);
// 2.从socket通信管道中得到一个字节输出流,用来发数据给服务端程序
OutputStream os = socket.getOutputStream();
// 3.把低级的字节输出流包装成数据流
DataOutputStream dos = new DataOutputStream(os);
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请说: ");
String msg = sc.nextLine();
// 一旦用户输入exit,就退出客户端程序
if("exit".equals(msg)){
System.out.println("欢迎你下次光临!退出成功");
dos.close();
socket.close();
break;
}
//4.开始写数据出去了
dos.writeUTF(msg);
dos.flush();
}
}
}
接收数据
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Res {
public static void main(String[] args) throws IOException {
System.out.println("------服务端启动成功------");
// 1.创建ServerSocket的对象,同时为服务端注册端口
ServerSocket serverSocket = new ServerSocket(8888);
// 2.使用serverSocket对象,调用一个accept方法,等待客户端的连接请求
Socket socket = serverSocket.accept();
// 3. 从socket通信管道中得到一个字节输入流
InputStream is = socket.getInputStream();
//4.把原始的字节输入流包装成数据输入流
DataInputStream dis = new DataInputStream(is);
while (true) {
try {
//5.使用数据输入流读取客户端发送的消息
String rs = dis.readUTF();
System.out.println(rs);
} catch (IOException e) {
System.out.println(socket.getRemoteSocketAddress()+"离线了");
socket.close();
dis.close();
break;
}
}
}
}
我们应该整一个多线程的写法,每个客户端写成一个线程
创建客户端
public class tcp {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",9999);
OutputStream os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
// 1. 多发多收
Scanner sc = new Scanner(System.in);
while (true) {
String msg = sc.nextLine();
if("886".equals(msg)){
System.out.println("下线");
break;
}
dos.writeUTF(msg);
}
}
}
创建服务端
public class res {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket =new ServerSocket(9999);
while (true) {
Socket socket = serverSocket.accept();
System.out.println("有人上线了"+socket.getRemoteSocketAddress());
new SeverSocketThread(socket).start();
}
}
}
我们看看线程的写法
package TCP_test;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class SeverSocketThread extends Thread{
private Socket socket;
public SeverSocketThread(Socket socket) {
this.socket = socket;
}
@Override
public void run()
{
try {
InputStream is = socket.getInputStream();
DataInputStream dis = new DataInputStream(is);
while (true) {
try {
String msg = dis.readUTF();
System.out.println(msg);
} catch (Exception e) {
System.out.println("有人下线了"+socket.getRemoteSocketAddress());
dis.close();
is.close();
socket.close();
break;
}
}
} catch (IOException e) {
System.out.println(socket.getRemoteSocketAddress() + "下线");
}
}
}