网络编程
网络编程
IP地址介绍
IP地址(internet Protocol)
唯一标示网络上的每一台计算机
IP地址的组成
32位,由4个8位二进制数组成
IP地址 = 网络地址 + 主机地址
网络地址:标示计算机或网络设备所在的网段
主机地址:标示特定主机或网络设备
局域网、城域网、广域网
IP地址的配置和检测
查看IP地址,检测网络是否畅通
查看本机IP地址:ipconfig
测试网络是否通畅:ping 目标IP地址
DNS域名解析
DNS:Domain Name System
网络服务器
通常指在网络环境下,具有较高计算能力,能够提供用户服务功能的计算机。
网络服务器
- 邮件服务器
- Web服务器
Microsoft IIS 服务器
APACHE Apache Tomcat 服务器 免费开源 遵循Http(超文本传输协议)
B/S:浏览器和服务器的程序 C/S:客户端和服务器的程序
网络通信协议
为了在网络中不同的计算机之间进行通信而建立的规则、标准或约定的集合(传输以帧为单位)
TCP面向连接传输 UDP面向无连接传输
Socket简介
socket :孔,插座
- 每一个Socket都提供不同的服务
- mySql服务3306端口
- SQL Server
- Oracle服务1512端口
- 服务和端口绑定
- 1-1023端口被系统占用
通信链路的断点就被称为“套接字”(英文名Socket)
是提供给应用程序的接口
Socket分类
流式套接字(SOCK_STREAM)
面向连接、可靠地数据传输服务-》TCP协议
数据报式套接字(SOCK_DGRAM)-》UDP协议
无连接服务
原始式套接字(SOCK_RAW) 一般不涉及
API在java.net包下
- Socket
- SeverSocket
- DatagramPacket
- DatagramSocket
- InetAddress
基于TCP协议的Socket编程
基于TCP协议的Socket网络通信
用来实现双向安全连接网络通信
Socket通信模型
进行网络通信时,Socket需要借助数据流来完成数据的传递工作
服务器端:
public class LoginSever {
public static void main(String[] args) {
try {
// 创建一个服务器Socket
ServerSocket serverSocket = new ServerSocket(5000);
// 使用accept()侦听并接受到此ServerSocket的连接
Socket socket = serverSocket.accept();
// 获得输入流,获得用户的请求
InputStream is = socket.getInputStream();
// 字符缓存流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// 创建缓存存储读取信息
byte[] buffer = new byte[1024];
// 声明变量存储信息
String info;
// 输出接受的信息
while ((info = br.readLine()) != null) {
System.out.println("客户端说:"+info);
}
// 发送回应
// 发送的信息
String output = "欢迎登陆!";
// 创建输出字符流
OutputStream os = socket.getOutputStream();
// 写入
os.write(output.getBytes());
// 关闭流
os.close();
br.close();
is.close();
// 关闭监听
socket.close();
// 关闭端口
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端:
public class LoginClient {
public static void main(String[] args) {
try {
// 创建一个客户端的Socket
Socket socket = new Socket("localhost",5000);
// 声明一个字符串用于发送数据
String info = "用户名:1234;密码:1234;";
// 建立一个输出流发送请求
OutputStream os = socket.getOutputStream();
os.write(info.getBytes());
// 暂时关闭输出流
socket.shutdownOutput();
// 接受客户端响应
InputStream is = socket.getInputStream();
BufferedReader bf = new BufferedReader(new InputStreamReader(is));
// 创建缓存接受响应
byte[] buffer = new byte[1024];
String reply;
while ((reply = bf.readLine()) != null) {
System.out.println("接收到服务器响应:"+reply);
}
// 释放资源
bf.close();
is.close();
os.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
网络编程传输的是对象
多线程处理多请求
服务器:
一直监听客户请求
一旦监听到有客户请求,立刻创建一个线程,开启线程
线程:
接收客户请求,给与客户一个响应
线程构造方法中去绑定客户端的Socket
客户端:
发送请求到服务器
接收服务器的响应
如何获得客户端IP?
InetAddress
示例:
/**
* 用户类
* @author 周太阳
* @version 1.0
* 2019年4月30日 下午2:47:17
*/
public class User {
/**姓名*/
private String name;
/**密码*/
private String password;
public User() {
super();
}
public User(String name, String password) {
super();
this.name = name;
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
/**
* 服务器多线程处理方式
* @author 周太阳
* @version 1.0
* 2019年4月30日 下午2:47:52
*/
public class LoginThread extends Thread{
private Socket socket;
public LoginThread() {
super();
}
public LoginThread(Socket socket) {
super();
this.socket = socket;
}
public void run() {
try (
// 获得输入流,获得用户的请求
InputStream is = socket.getInputStream();
// 字符缓存流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// 创建输出字符流
OutputStream os = socket.getOutputStream();
){
// 创建缓存存储读取信息
byte[] buffer = new byte[1024];
// 声明变量存储信息
String info;
// 输出接受的信息
while ((info = br.readLine()) != null) {
System.out.println("客户端说:"+info);
}
// 获得对应主机的IP地址
InetAddress ia = socket.getInetAddress();
// 将IP地址转换为字符串
String hostAddress = ia.getHostAddress();
System.out.println("用户的IP地址是:"+hostAddress);
// 发送信息回应
String output = "欢迎登陆!";
// 写入
os.write(output.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
基于UDP协议的Socket编程
TCP | UDP | |
---|---|---|
是否连接 | 面向连接 | 面向非连接 |
传输可靠性 | 可靠 | 不可靠 |
速度 | 慢 | 快 |
基于UDP协议的Socket网络编程步骤:
- 利用DatagramPacket对象封装数据包
- 利用DatagramSocket发送数据包
- 利用DatagramSocket接收数据包
- 利用DatagramPacket处理数据包
位于java.net包
new String();里面有很多构造,可以看下。
socket.send(DatagramPacket p) : void // 发送包
socket.receive(DatagramPacket p) : void // 接收包
案列:
/**
* UDP客户端
* @author 周太阳
* @version 1.0
* 2019年4月30日 下午2:43:27
*/
public class LoginClient {
public static void main(String[] args) {
// 买巧克力
String info = "心形巧克力";
byte[] bs = info.getBytes();
// 对方地址或邮编
try (
// 快递点
DatagramSocket socket = new DatagramSocket();
){
// 对方地址和邮编(端口号)
InetAddress ia = InetAddress.getByName("localhost");
// 包装礼物
DatagramPacket dp = new DatagramPacket(bs, bs.length,ia,5000);
socket.send(dp);
// 接收服务器信息
// 创建一个字节缓存接收信息
byte[] bytes = new byte[1024];
// 创建一个解包器
DatagramPacket dp1 = new DatagramPacket(bytes,bytes.length);
// 接收包
socket.receive(dp1);
// 用字符串解包
String str = new String(dp1.getData(), 0, dp1.getData().length);
System.out.println("服务器说:"+str);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* UDP服务器
* @author 周太阳
* @version 1.0
* 2019年4月30日 下午2:43:37
*/
public class LoginServer {
public static void main(String[] args) {
// 创建一个缓存接收包
byte[] receive = new byte[1024];
// 创建一个解包器
DatagramPacket dp = new DatagramPacket(receive, receive.length);
try (
// 创建一个接收器
DatagramSocket ds = new DatagramSocket(5000);
){
// 接收包
ds.receive(dp);
// 用字符串解包
String str = new String(dp.getData(),0,dp.getData().length);
System.out.println("客户端说:"+str);
// 给客户端发送信息
String info = "一箱饮料";
// 变成字节数组
byte[] gift= info.getBytes();
// 打包
DatagramPacket dp1 = new DatagramPacket(gift,gift.length,dp.getSocketAddress());
// 发送
ds.send(dp1);
} catch (Exception e) {
// TODO: handle exception
}
}
}