网络编程
什么是网络
- 由点和线构成,表示诸多对象间的相互联系关系
计算机网络
- 为了实现资源的共享和信息传递,通过通信线路连接起来的的若干主机(Host)
- 按照地理范围网络分为
- 局域网
- 城域网
- 广域网
- 互联网:点对点
- 万维网:端与端
- 物联网:物与物
- 网络编程:让计算机与计算机之间建立连接,进行通信
网络模型
1.OSI模型(开放式系统互联)
2.TCP/IP模型
- 一组用于实现网络互连的通信协议,将协议分成四个层次
通信协议
- TCP协议:Transmission Control Protocol 传输控制协议
- 是一种面向连接,可靠的,基于字节流的传输层通信协议,数据大小无限制,建立连接过程需要三次握手,断开连接的过程需要四次握手
- UDP协议:User Datagram Protocol 用户数据报协议
- 是一种无连接的传输层协议,提供面向事物的简单不可靠信息传送服务,每个包大小64KB
- IP协议:Internet Protocol互联网协议/网际协议
- 负责数据从一台机器发送到另一台机器
- 给互联网每个电脑分配一个唯一标识(ip地址)
IP与端口
1.IP
- IP地址分为两种:
-
IPV4:4个字节32位整数,并分成4段8位的二进制数,用圆点隔开,每8位整数可以转换为一个0-255的十进制整数
格式:D.D.D.D 例如:255.255.255.255
-
IPV6:16字节128位整数,并分成8段十六进制数,每16位用圆点隔开,每16位整数可以转化为0-65535的十进制数
格式:x.x.x.x.x.x.x.x
例如:FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF
-
2.端口(port)
- 端口号:在通信实体上进行网络通讯程序的唯一标识
- 端口分类:
- 公认端口:0-1023
- 注册端口:1024-49151
- 动态或私有端口:49151-65535
- 常用端口:
- mysql:3306
- oracle:1521
- tomcat:8080
- SMTP:25
- web服务器:80
- FTP服务器:21
网络编程
1.InetAddress类
- 概念:表示互联网协议(IP)地址对象,封装了与该ip地址的所有信息,并提供获取信息的方法
- 方法
/**
* 使用InetAddress类
*/
public class Demo01 {
public static void main(String[] args) throws Exception{
//创建本机ip地址对象
//1.1getLocalHost()方法
InetAddress localHost = InetAddress.getLocalHost();
System.out.println("ip地址:"+localHost.getHostAddress()+"主机名:"+localHost.getHostName());
//1.2getByName("ip地址")方法
InetAddress address1 = InetAddress.getByName("192.168.0.104");
System.out.println("ip地址:"+address1.getHostAddress()+"主机名:"+address1.getHostName());
//1.3getByName("127.0.0.1")方法
InetAddress address2 = InetAddress.getByName("127.0.0.1");
System.out.println("ip地址:"+address2.getHostAddress()+"主机名:"+address2.getHostName());
//1.4getByName("localhost")方法
InetAddress address3 = InetAddress.getByName("localhost");
System.out.println("ip地址:"+address3.getHostAddress()+"主机名:"+address3.getHostName());
//2.创建局域网ip地址对象
InetAddress address4 = InetAddress.getByName("192.168.0.105");
System.out.println("ip地址:"+address4.getHostAddress()+"主机名:"+address4.getHostName());
System.out.println("两秒后有没到连接到达:"+address4.isReachable(2000));
//创建外网ip地址对象
InetAddress address5 = InetAddress.getByName("www.baidu.com");
System.out.println("ip地址:"+address5.getHostAddress()+"主机名:"+address5.getHostName());
System.out.println("两秒后有没到连接到达:"+address5.isReachable(2000));
System.out.println("--------------------");
InetAddress[] addresses = InetAddress.getAllByName("www.baidu.com");
for (InetAddress address : addresses) {
System.out.println(address.getHostAddress());
}
}
}
2.基于TCP网络编程
- Socket编程
- Socket(套接字)是网络中的一个通信节点
- 分为客户端Socket与服务器ServerSocket
- 通信要求:IP地址+端口号
- 开发步骤
- 服务器端:
- 创建SeverSocket,指定端口号
- 调用accept等待客户端接入
- 使用输入流,接收请求数据到服务器(等待)
- 使用输出流,发送响应数据给客户端
- 释放资源
- 客户端:
- 创建Socket,指定服务器ip+端口号
- 使用输出流,发送请求数据给服务器
- 使用输入流,接受响应数据到客户端(等待)
- 释放资源
- 服务器端:
- 服务器和客户端之间通信
/**
* - 客户端:
* - 创建Socket,指定服务器ip+端口号
* - 使用输出流,发送请求数据给服务器
* - 使用输入流,接受响应数据到客户端(等待)
* - 释放资源
*/
public class Demo03 {
public static void main(String[] args) throws Exception{
//创建Socket,指定服务器ip+端口号
Socket socket = new Socket("localhost", 8898);
//使用输出流,发送请求数据给服务器
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "utf-8"));
bufferedWriter.write("好久不见!");
bufferedWriter.newLine();
bufferedWriter.flush();
//使用输入流,接受响应数据到客户端(等待)
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
String data = bufferedReader.readLine();
System.out.println("服务端是否成功接收:"+data);
//释放资源
bufferedReader.close();
bufferedWriter.close();
socket.close();
}
}
/**
* - 服务器端:
* - 创建SeverSocket,指定端口号
* - 调用accept等待客户端接入
* - 使用输入流,接收请求数据到服务器(等待)
* - 使用输出流,发送响应数据给客户端
* - 释放资源
*/
public class Demo02 {
public static void main(String[] args) throws Exception{
//创建SeverSocket,指定端口号
ServerSocket serverSocket = new ServerSocket(8898);
//调用accept等待客户端接入,阻塞方法
System.out.println("服务器已启动.....");
Socket accept = serverSocket.accept();
//使用输入流,接收请求数据到服务器(等待)
InputStream is = accept.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is, "utf-8"));
String data = bufferedReader.readLine();
System.out.println("客户发送:"+data);
//使用输出流,发送响应数据给客户端
OutputStream outputStream = accept.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "utf-8"));
bufferedWriter.write("成功接收数据");
bufferedWriter.newLine();
bufferedWriter.flush();
//释放资源
bufferedWriter.close();
bufferedReader.close();
accept.close();
serverSocket.close();
}
}
- tcp编程实现客户端上传文件给服务端
/**
* 服务端
*/
public class Demo04 {
public static void main(String[] args) throws Exception{
//创建ServerSocket
ServerSocket serverSocket = new ServerSocket(9999);
//接收客户端请求Socket
System.out.println("服务器启动...........");
Socket accept = serverSocket.accept();
//获取输入流
InputStream inputStream = accept.getInputStream();
BufferedInputStream bis = new BufferedInputStream(inputStream);
//边读边写
FileOutputStream fos = new FileOutputStream("d://3.jpg");
int data=0;
while ((data=bis.read())!=-1){
fos.write((char)data);
fos.flush();
}
//关闭资源
fos.close();
bis.close();
accept.close();
serverSocket.close();
System.out.println("接收完毕");
}
}
/**
* 客户端
*/
public class Demo05 {
public static void main(String[] args) throws Exception{
//创建Socket
Socket socket = new Socket("localhost", 9999);
//获取输出流
OutputStream outputStream = socket.getOutputStream();
//边读边发送
FileInputStream fis = new FileInputStream("d://2.jpg");
BufferedInputStream bis = new BufferedInputStream(fis);
int data=0;
while ((data=bis.read())!=-1){
outputStream.write((char)data);
outputStream.flush();
}
//关闭资源
bis.close();
outputStream.close();
socket.close();
System.out.println("发送完毕");
}
}
- 实现多个客户端发消息给服务器
/**
* 服务器
*/
public class Demo06 {
public static void main(String[] args) throws Exception{
//创建ServerSocket
ServerSocket serverSocket = new ServerSocket(9998);
System.out.println("服务器已经启动。。。。。");
//接收客户端的请求Socket
while (true){
Socket accept = serverSocket.accept();
System.out.println(accept.getInetAddress()+"进来了。。。。");
Runnable runnable = new Runnable(){
@Override
public void run() {
InputStream is=null;
BufferedReader br=null;
try {
is= accept.getInputStream();
br = new BufferedReader(new InputStreamReader(is,"utf-8"));
while (true){
String data = br.readLine();
if (data == null){
break;
}
System.out.println(accept.getInetAddress() +"发送的数据是:"+data);
if (data.equals("886")||data.equals("bye")){
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
br.close();
accept.close();
System.out.println(accept.getInetAddress()+"退出了!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
new Thread(runnable).start();
}
}
}
/**
* 客户端
*/
public class Demo07 {
public static void main(String[] args) throws Exception{
//创建Socket
Socket socket = new Socket("localhost", 9998);
//获取输入流
OutputStream os = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, "utf-8"));
//控制输入
Scanner input = new Scanner(System.in);
while (true){
String data = input.nextLine();
bw.write(data);
bw.newLine();
bw.flush();
if (data.equals("886")||data.equals("bye")){
break;
}
}
//关闭资源
bw.close();
socket.close();
}
}
- 基于tcp实现登录注册功能
- loginThread(登录服务器)
public class LoginThread extends Thread{
@Override
public void run() {
while (true) {
try {
//创建ServerSocket
ServerSocket serverSocket = new ServerSocket(8888);
//接收客户端请求
Socket accept = serverSocket.accept();
//获取输入输出流
BufferedReader br = new BufferedReader(new InputStreamReader(accept.getInputStream(), "utf-8"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream(), "utf-8"));
//接收数据
String json = br.readLine();
//定制数据格式
String[] infos = json.substring(1, json.length() - 1).split(",");
String id = infos[0].split(":")[1];
//加载配置文件
Properties properties = Tools.loadProperties();
//检验信息是否正确
if (properties.containsKey(id)){
String password = infos[1].split(":")[1];
String property = properties.getProperty(id);
String[] split = property.substring(1, property.length() - 1).split(",");
String pwd = split[2].split(":")[1];
if (pwd.equals(password)){
System.out.println("登录成功。。。。");
}else {
System.out.println("密码错误。。。");
}
bw.write("登录成功。。。。");
} else {
bw.write("用户名或者密码错误。。。。");
}
bw.newLine();
bw.flush();
//关闭资源
br.close();
accept.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- RegistThread(注册服务器)
public class RegistThread extends Thread{
@Override
public void run() {
while (true) {
try {
//创建ServerSocket
ServerSocket serverSocket = new ServerSocket(6666);
//接收客户端请求
Socket accept = serverSocket.accept();
//获取输入输出流
BufferedReader br = new BufferedReader(new InputStreamReader(accept.getInputStream(), "utf-8"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream(), "utf-8"));
//接收数据
String json = br.readLine();
//定制数据格式
String[] infos = json.substring(1, json.length() - 1).split(",");
String id = infos[0].split(":")[1];
//加载配置文件
Properties properties = Tools.loadProperties();
//判断是否存在
if (properties.containsKey(id)) {
bw.write("此用户已存在。。。。");
} else {
//保存数据
Tools.saveProperties(json);
bw.write("注册成功。。。。");
}
bw.newLine();
bw.flush();
//关闭资源
br.close();
accept.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- UserServer (用户服务器)
public class UserServer {
public static void main(String[] args) {
new RegistThread().start();
new LoginThread().start();
}
}
- Tools(工具类)
/**
* 配置文工具类
*/
public class Tools {
//加载配置文件
public static Properties loadProperties(){
Properties properties = new Properties();
File file = new File("users.properties");
if (file.exists()){
FileInputStream fis = null;
try {
fis=new FileInputStream(file);
properties.load(fis);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (file!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return properties;
}
//保存配置文件
public static void saveProperties(String json){
//定制数据格式
String[] infos = json.substring(1, json.length() - 1).split(",");
String id = infos[0].split(":")[1];
FileOutputStream fos=null;
try {
fos = new FileOutputStream("users.properties",true);
Properties properties = new Properties();
properties.setProperty(id,json);
properties.store(fos,"");
} catch (Exception e) {
e.printStackTrace();
}finally {
if (fos!=null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- UserClient(用户客户端)
public class UserClient {
public static void main(String[] args) throws Exception{
System.out.println("-------请选择 1注册 2登录---------");
Scanner scanner = new Scanner(System.in);
int choice = scanner.nextInt();
switch (choice){
case 1:
regist();
break;
case 2:
login();
break;
default:
break;
}
}
public static void regist() throws Exception{
//创建socket
Socket socket = new Socket("localhost", 6666);
//获取输入输出流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "utf-8"));
//获取用户信息
String json = getRegistInfo();
//发送数据
bw.write(json);
bw.newLine();
bw.flush();
//接收数据
System.out.println("服务器回复:"+br.readLine());
//关闭资源
bw.close();
br.close();
socket.close();
}
public static void login() throws Exception{
//创建socket
Socket socket = new Socket("localhost", 8888);
//获取输入输出流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "utf-8"));
//获取用户信息
String json = getLoginInfo();
//发送数据
bw.write(json);
bw.newLine();
bw.flush();
//接收数据
System.out.println("服务器回复:"+br.readLine());
//关闭资源
bw.close();
br.close();
socket.close();
}
public static String getRegistInfo(){
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户编号");
int id = scanner.nextInt();
System.out.println("请输入名字");
String name = scanner.next();
System.out.println("请输入密码");
String password = scanner.next();
System.out.println("请输入年龄");
int age = scanner.nextInt();
String json="{id:"+id+",name:"+name+",password:"+password+",age:"+age+"}";
return json;
}
public static String getLoginInfo(){
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户编号");
int id = scanner.nextInt();
System.out.println("请输入密码");
String password = scanner.next();
String json="{id:"+id+",password:"+password+"}";
return json;
}
}
- users.properties(配置文件)
#
#Fri Dec 04 15:57:03 CST 2020
123={id\:123,name\:\u6B27\u5C11,password\:123,age\:23}
#
#Fri Dec 04 16:25:47 CST 2020
1234={id\:1234,name\:\u6B27\u5C11,password\:1234,age\:24}
3.基于UDP网络编程
- 实现简单的发送消息
- UdpClient
public class UdpClient {
public static void main(String[] args) throws Exception{
//建立一个socket
DatagramSocket ds = new DatagramSocket();
//建个包
String msg="你好啊,服务器";
//发送给谁
InetAddress localhost = InetAddress.getByName("localhost");
DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, 9997);
//发送包
ds.send(packet);
//关闭流
ds.close();
}
}
- UdpServer
public class UdpServer {
public static void main(String[] args) {
//创建Socket
DatagramSocket ds=null;
try {
//开放端口
ds=new DatagramSocket(9997);
byte[] bytes = new byte[1024];
//创建数据包
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//接收数据
ds.receive(dp);//阻塞接收
System.out.println(dp.getAddress());
System.out.println(new String(dp.getData(),0,dp.getLength()));
} catch (Exception e) {
e.printStackTrace();
}finally {
//关闭资源
if (ds!=null){
ds.close();
}
}
}
}
- 循环发送消息
public class UDPDemo01 {
public static void main(String[] args) throws Exception{
//创建socket,开放端口
DatagramSocket ds = new DatagramSocket();
//准备数据,控制台读取
BufferedReader br = new BufferedReader(new InputStreamReader(System.in,"utf-8"));
while (true){
String data = br.readLine();
byte[] datas = data.getBytes();
InetAddress address = InetAddress.getByName("localhost");
DatagramPacket dp = new DatagramPacket(datas, 0, datas.length, address, 6666);
//发送数据
ds.send(dp);
if (data.equals("bye")){
break;
}
}
//关闭资源
ds.close();
}
}
public class UDPDemo02 {
public static void main(String[] args) throws Exception{
//开放端口
DatagramSocket ds = new DatagramSocket(6666);
while (true){
//准备接收包
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,0,bytes.length);
//阻塞式接收包数据
ds.receive(dp);
//断开连接
byte[] data = dp.getData();
String receiveData = new String(data, 0, dp.getLength());
System.out.println(receiveData);
if (receiveData.equals("bye")){
break;
}
}
//关闭资源
ds.close();
}
}