网络编程
在Java中,网络编程是指使用Java语言进行网络通信的编程技术。这种技术使得位于不同地理位置的计算机能够通过网络进行通信,实现资源共享和信息传递。
一、定义
Java网络编程是Java语言在网络通信方面的应用,它利用Java提供的网络类库和API,通过编写网络程序实现不同计算机之间的通信。Java网络编程涉及许多概念和技术,如IP地址、端口号、套接字(Socket)和通信协议等。
二、用处
Java网络编程在多个领域都有广泛的应用,例如:
- Web应用程序:Java网络编程技术被广泛应用于Web应用程序的开发中,如Servlet、JSP等技术都是基于Java网络编程实现的。
- 客户端/服务器应用程序:Java网络编程可以实现客户端和服务器之间的通信,使得不同计算机可以共享数据和服务。
- 网络游戏:网络游戏需要实时更新和传输数据,Java网络编程技术可以实现这种实时通信,保证游戏的流畅性和互动性。
三、使用方法
在Java中进行网络编程,可以使用Socket和ServerSocket类来实现基于TCP协议的网络通信,也可以使用DatagramSocket和DatagramPacket类来实现基于UDP协议的网络通信。具体使用方法如下:
- TCP通信:
- 创建ServerSocket对象,绑定监听端口;
- 调用ServerSocket对象的accept()方法,等待客户端连接;
- 创建一个Socket对象,表示与客户端的连接;
- 通过Socket对象的getInputStream()和getOutputStream()方法获取输入/输出流,进行数据传输;
- 关闭连接。
- UDP通信:
- 创建DatagramSocket对象,绑定端口;
- 创建DatagramPacket对象,封装要发送的数据和接收方的IP地址及端口号;
- 调用DatagramSocket对象的send()方法发送数据;
- 调用DatagramSocket对象的receive()方法接收数据;
- 解析接收到的DatagramPacket对象中的数据;
- 关闭连接。
四、注意事项
在进行Java网络编程时,需要注意以下几点:
- 网络安全:网络通信涉及到数据的安全性和隐私性,因此需要采取适当的安全措施来保护数据。例如,使用加密技术、身份验证和访问控制等。
- 异常处理:网络通信过程中可能会出现各种异常情况,如连接中断、数据传输错误等。因此,在编写网络程序时需要添加适当的异常处理代码,以确保程序的稳定性和可靠性。
- 性能优化:网络通信涉及到数据传输和处理,因此需要关注程序的性能问题。可以采取一些优化措施来提高程序的性能,如使用缓存、减少数据传输量、优化算法等。
- 代码规范:在编写Java网络程序时,需要遵循一定的代码规范,以提高代码的可读性和可维护性。例如,使用恰当的变量名、注释和缩进等。
- 测试和调试:在开发过程中,需要进行充分的测试和调试,以确保程序的正确性和稳定性。可以使用一些测试工具和调试工具来帮助发现和解决问题。
网络编程三要素
-
Ip
- 设备在网络中的地址,是唯一的标识
-
端口号确定接收数据的软件
- 应用程序在设备中的唯一的标识
-
协议确定网络传输的规则
-
数据在网络中传输的规则
-
常见的协议有UDP,TCP,http,https,ftp
-
网络编程的三要素包括IP地址、端口和协议
- IP地址:在网络编程中,IP地址用于标识网络中的设备。它是一个由四个8位二进制数(通常用点分十进制表示)组成的地址,如192.168.1.1。IP地址分为网络号和主机号两部分,网络号用于标识设备所处的网络,而主机号则用于标识该网络中的具体设备。通过IP地址,我们可以确定要接收数据的计算机和识别发送的计算机。
- 端口:在网络通信中,端口号用于唯一标识设备中的应用程序。端口号的范围是0到65535,其中0到1023是公认端口,用于系统服务,如HTTP(80端口)和FTP(21端口)。1024到49151是注册端口,可以用于用户自定义服务。当数据到达目标设备时,操作系统会根据端口号将数据传递给相应的应用程序进行处理。
- 协议:协议是网络编程中的另一个关键要素,它定义了数据在网络中的传输方式、数据格式以及通信双方必须遵循的规则。常见的网络协议包括TCP(传输控制协议)和UDP(用户数据报协议)。TCP协议是面向连接的协议,提供可靠的数据传输服务,适用于对数据传输有较高要求的应用场景,如文件传输和网页浏览。UDP协议则是无连接的协议,传输速度快但可靠性较低,适用于对实时性要求较高但对数据完整性要求不高的应用场景,如视频直播和在线游戏。
常见的cmd命令
127.0.0.1
- 永远表示本机
ipconfig
- 查看本机ip地址
ping
- 检查网络是否畅通
常见的两个协议(UDP TCP)
UDP
-
(User Datagram Protocol),用户数据协议
-
UDP是面向无连接通信协议
-
速度快,有大小限制,一次最多发送64k,数据不安全,易丢失数据
例子代码1
- 注意事项:要先运行接收数据的代码,然后再运行发送数据的代码
package com.mohuanan.test02;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class Test02 {
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);
//3. 拿出里面的数据
ds.receive(dp);
byte[] data = dp.getData();
int len = dp.getLength();
int port = dp.getPort();
InetAddress address = dp.getAddress();
//4. 释放资源
ds.close();
String string = new String(data,0,len);
System.out.println(string);
System.out.println("是从"+address+"这台电脑里面传输过来的");
System.out.println("端口为: "+port);
}
}
package com.mohuanan.test02;
import java.io.IOException;
import java.net.*;
public class Test01 {
public static void main(String[] args) throws IOException {
//1. 创建DatagramSocket对象
DatagramSocket ds = new DatagramSocket();
String str = "你好!";
byte[] bytes = str.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
//2. 创建DatagramPacket对象
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,10086);
//3. 将打包好的数据发送
ds.send(dp);
//4. 释放资源
ds.close();
}
}
例子代码2(聊天室)
package com.mohuanan.exercise01;
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class SendMessagee {
public static void main(String[] args) throws IOException {
//1. 创建DatagramSocket对象
DatagramSocket ds = new DatagramSocket();
//2. 打包数据
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入您要输入的话: ");
String word = sc.nextLine();
if(word.equals("886")){
break;
}
byte[] bytes = word.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,10086);
//3. 发送数据
ds.send(dp);
}
//4. 释放资源
ds.close();
}
}
package com.mohuanan.exercise01;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ReceiveMessage {
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);
while (true) {
ds.receive(dp);
//3. 解析这个包
byte[] data = dp.getData();
String ip = dp.getAddress().getHostAddress();
int len = dp.getLength();
int port = dp.getPort();
String name = dp.getAddress().getHostName();
System.out.println("ip为: "+ip+",主机名为: "+name+"的人,发送了数据"+new String(data,0,len));
System.out.println("端口为: "+port);
}
//while(true)死循环
}
}
运行结果
三种通信方式
UDP(用户数据报协议)的三种通信方式分别是:
- 单播(Unicast):这是点对点的通信方式。当一个UDP客户端需要将数据发送到另一个特定的UDP客户端时,它使用单播模式。在单播模式下,数据报只发送到指定的接收方,确保数据的安全性和准确性。
- 广播(Broadcast):广播模式允许一个UDP客户端发送数据报,使得在同一网络范围内的所有其他UDP客户端都能接收到该数据报。这通常用于网络发现协议,其中设备通过广播其存在来让其他设备知道其在线状态。广播地址通常是255.255.255.255。
- 组播(Multicast):也称为多播,组播模式允许UDP客户端加入到一个特定的组播IP地址指定的多播组中。当组内的成员向组播地址发送数据报时,组内的所有成员都可以接收到这些数据报。这种方式类似于QQ群的功能,可以实现一对多的通信。
这三种通信方式各有特点,适用于不同的应用场景。单播模式适用于需要确保数据安全和准确性的场景,广播模式适用于需要让网络中的所有设备都知道某个事件或状态的场景,而组播模式则适用于需要实现一对多通信的场景。
TCP
-
(Transmission Contol Protocol)传输控制协议
-
TCP是面向连接的通信协议
-
速度慢,没有大小的限制,数据安全
综合练习(多发多写)
package com.mohuanan.exercise;
import java.io.*;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
//客户端
//创建Socket的对象
Socket socket = new Socket("127.0.0.1", 10005);
//读取本地的文件图片
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("client\\client01.jpg"));
//转化成为缓冲流
OutputStream outputStream = socket.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(outputStream);
//开始读取本地的图片
byte[] bytes = new byte[1024 * 1];
int len;
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
//结束标记 为了让服务端停止
socket.shutdownOutput();
//获取服务端反馈的消息
InputStream is = socket.getInputStream();
//把读取到的字节流转化成为字符流
InputStreamReader isr = new InputStreamReader(is);
//使用缓冲流进行快速读取
BufferedReader br = new BufferedReader(isr);
String result = br.readLine();
System.out.println(result);
//释放资源
socket.close();
bis.close();
}
}
package com.mohuanan.exercise;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Server {
public static void main(String[] args) throws IOException {
//服务端
//创建ServerSocket的对象
ServerSocket ss = new ServerSocket(10005);
ThreadPoolExecutor pool = new ThreadPoolExecutor(
3,//核心线程数
16,//最多线程数
60,//空闲的时间
TimeUnit.SECONDS,//空闲的时间单位
new ArrayBlockingQueue<>(2),//队伍的长度
Executors.defaultThreadFactory(),//线程工厂
new ThreadPoolExecutor.AbortPolicy()//拒绝策略
);
//接收连接
//返回一个客户端的对象
while (true) {
Socket accept = ss.accept();
//使用线程池
pool.submit(new MyRunnable(accept));
}
//释放资源
}
}
package com.mohuanan.exercise;
import java.io.*;
import java.net.Socket;
import java.util.UUID;
public class MyRunnable implements Runnable{
Socket accept;
public MyRunnable(Socket socket){
this.accept = socket;
}
@Override
public void run() {
try {
//获取客户端的输入流,并把这个字节流使用缓冲流提高效率
BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
//将获取到的数据写到本地文件
//避免文件名重复
String name = UUID.randomUUID().toString().replace("-","");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("server\\"+name+".jpg"));
byte[] bytes = new byte[1024*1];
int len;
while((len = bis.read(bytes) )!= -1){
bos.write(bytes,0,len);
}
//回写数据
OutputStream outputStream = accept.getOutputStream();
BufferedWriter bw2 = new BufferedWriter(new OutputStreamWriter(outputStream));
bw2.write("上传成功");
bw2.newLine();
bw2.flush();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
accept.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}