Java网络通信
# Java网络通信
# IP地址
Class InetAddress
java.lang.Object java.net.InetAddress
该类表示Internet协议(IP)地址。IP地址是由IP使用的32位或128位无符号数字,一般IPv4格式范围:0.0.0.0~255.255.255.255
特殊IP地址:本地回送地址 不进行网络传输 127.0.0.1
返回本地
InetAddress类常用方法
返回 | 方法 | 说明 |
---|---|---|
String | getHostName() | 获取IP地址的主机名 |
String | getHostAddress() | 获取IP地址字符串 |
InetAddress | getByName(String host) | 获取与Host对应的InetAddress对象 |
InetAddress | getLocalHost() | 返回本主机的InetAddress对象 |
InetAddress[] | getAllByName(String host) | 获取指定主机的所有地址 |
其余的方法自查API
# TCP程序设计
TCP网络设计是利用Socket类(套接字)编写通信程序。 PS:套接字可以比作是一个连接装置(工具,像用电器必须要插插头连接才能使用!!
TCP协议进行通信应用程序分为 服务器程序 、 客户机程序
实现流程
1. 创建服务器 实例 `ServerSocket()对象` 2. 等待连接客户端 用服务器套接字 `accept()方法` 3. 连接客户端 实例 `Socket()对象` 4. 发送信息 或 接收信息 (信息交互的是**字节流**) 发送信息:用客户端套接字 `getOutputStream()方法` 进行输出 接收信息 :用客户端套接字 `getInputStream()方法` 进行输入
# 服务器套接字
Class ServerSocket
java.lang.Object java.net.ServerSocket
ServerSocket类 实现了服务器套接字。等待通过网络进入的请求。服务器会根据该请求执行一些操作,然后可能将结果返回给请求者
构造方法
ServerSocket() ServerSocket(int port) ServerSocket(int port, int backlog) ServerSocket(int port, int backlog, InetAddress bindAddr)
port: 端口号 backlog: 请求进入连接队列的最大长度 bindAddr: 服务器将绑定到的本地InetAddress
方法
修饰符 | 方法 | 说明 |
---|---|---|
Socket | accept() | 等待客户端的连接,连接则创建套接字 |
boolean | isBound() | 判断ServerSocket的绑定状态 |
InetAddress | getInetAddress() | 获取服务器套接字的本地地址 |
boolean | isClosed() | 获取服务器套接字的关闭状态 |
void | close() | 关闭服务器套接字 |
void | bind(SocketAddress endpoint) | 将ServerSocket绑定到特定地址(IP地址、端口号) |
其余的方法自查API
# 客户端套接字
Class Socket java.lang.Object java.net.Socket
Socket类 实现客户端套接字, 套接字是两台机器之间通讯的端点
构造方法
Socket() Socket(IntetAddress address , int port) Socket(String host , int port)
IntetAddress: IP地址 port: 端口号 host: 主机地址
方法
修饰符 | 方法 | 说明 |
---|---|---|
InputStream | getInputStream() | 获取套接字输入流 |
OutputStream | getOutputStream() | 获取套接字输出流 |
boolean | isConnected() | 查看套接字是否连接 |
void | close() | 关闭套接字 |
InetAddress | getInetAddress() | 返回连接主机的地址 |
其余的方法自查API
# UDP程序设计
UDP通讯方式,输出快、支持多人,但数据不能保证完好接收。UDP通信模式是将数据打包(数据包),然后接收人接收数据包查看。(其原理类似于电台广播的发放与收音机的接收!
实现流程
发送端:
- 实例UDP
DatagramSocket()对象
- 实例数据包
DatagramPacket()对象
(必须全参实例,否则无法接收)- 广播式发送
DatagramSocket.send(DatagramPacket data)方法
接收端:
- 实例UDP
DatagramSocket()对象
绑定端口号 (对应 数据包 中的端口号)- 实例数据包
DatagramPacket()对象
(获取信息为前提,参数随意)- DatagramPacket类的receive()方法接收UDP包
- 接收数据包
DatagramSocket.receive(DatagramPacket data)方法
进行接收- 获取字节包中的字节内容
DatagramPacket.getData()
(最后进行转换即可)
PS:receive()方法接收数据并返回,如未接收到数据,则阻塞至收到为止!!
# 数据包
Class DatagramPacket
java.lang.Object java.net.DatagramPacket
数据包用于实现无连接分组传送服务(类似于快递运送的包裹
构造方法
DatagramPacket(byte[] bt, int len) DatagramPacket(byte[] bt,int off , int len) DatagramPacket(byte[] bt ,int len ,InetAddress address ,int port) DatagramPacket(byte[] bt ,int off ,int len ,InetAddress address ,int port)
bt: 发送数据(字节流) off: 有效数据 在数组中的起始点 len: 有效数据 在数组中的长度 address: 指定IP(InetAddress 实例对象) port: 端口号
方法
返回 | 方法 | 说明 |
---|---|---|
InetAddress | getAddress() | 获取 对方主机 IP对象 |
byte[] | getData() | 获取 数据包 |
int | getLength() | 获取 数据包的长度 |
int | getOffset() | 获取 数据包 起始偏移量 |
int | getPort() | 获取 对方主机 端口 |
SocketAddress | getSocketAddress() | 获取 发送方的主机 IP地址 和 端口 |
void | setAddress(InetAddress iaddr) | 设置 发送至对方主机 IP |
void | setData(byte[] buf) | 设置 数据包的数据缓冲区 |
void | setData(byte[] buf, int offset, int length) | 设置 数据包的数据缓冲区,指定范围的有效数据 |
void | setLength(int length) | 设置数据包的长度 |
void | setPort(int iport) | 设置 发送至对方主机 端口号 |
void | setSocketAddress(SocketAddress address) | 设置 发送至对方主机 SocketAddress对象 |
# 数据包套接字
Class DatagramSocket
java.lang.Object java.net.DatagramSocket
数据包套接字用于 发送 和 接收 数据包的套接字(类似于运送快递的快递员
构造方法
DatagramSocket() DatagramSocket(int port) DatagramSocket(int port , InetAddress addr)
port: 端口号 address: IP地址
方法
修饰符 | 方法 | 说明 |
---|---|---|
void | bind(SocketAddress addr) | 绑定地址和端口 |
void | close() | 关闭数据套接字 |
void | receive(DatagramPacket p) | 套接字接收数据包(有堵塞效果) |
void | send(DatagramPacket p) | 套接字发送数据包 |
其余的方法自查API
# 组播套接字
Class MulticastSocket
java.lang.Object java.net.DatagramSocket java.net.MulticastSocket
播组发送消息时,向该主机和端口发送消息,接收者在播放的前提才能接收到消息
构造方法
MulticastSocket() MulticastSocket(int port) MulticastSocket(SocketAddress bindaddr)
port: 端口号 bindaddr: SocketAddress对象
方法
返回 | 方法 | 说明 |
---|---|---|
void | joinGroup(InetAddress addr) | 加入广播组 |
void | leaveGroup(InetAdderss addr) | 离开广播组 |
InetAdderss | getInterface() | 获取数据包接口的IP地址 |
更多方法自行API
# 代码索引
# IP操作
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Address {
public static void main(String[] args) {
try {
InetAddress myip = InetAddress.getLocalHost();
System.out.println("本机名:"+myip.getHostName());
System.out.println("本机IP:"+myip.getHostAddress());
//获取百度的所有IP地址
InetAddress baiduip[] = InetAddress.getAllByName("www.baidu.com");
for(InetAddress tmp : baiduip){
System.out.println("IP:"+tmp.getHostAddress());
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
/*
*
* 运行结果:
* 本机名:LAPTOP-GDSLL8RB
* 本机IP:192.168.43.84
* IP:14.215.177.38
* IP:14.215.177.39
*
* */
# TCP信息交互
服务端:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer {
/**
* server - 服务器对象
* reader - 接收用户信息(缓冲字符输入流)
* writer - 输出内容(文本输出流)
* socket - 套接字(进行与客户端数据交互的渠道)
* count - 记录目前用户数
*/
private ServerSocket server = null;
private BufferedReader reader = null;
private PrintWriter writer = null;
private Socket socket = null;
private int count = 0;
public static void main(String[] args) {
new MyServer().serverStart();
}
private void serverStart() {
try {
server = new ServerSocket(8848);
System.out.println("服务器已创建! ");
System.out.println("等待客户端连接。。。");
socket = server.accept();
count++;
System.out.println("一个用户连接!");
/**发送内容
* 利用字节输出流实例 文本流对象
*/
writer = new PrintWriter(socket.getOutputStream());
//注意 : 如果没有及时刷新缓存则会发出的是 空
writer.println("欢迎连接本服务器!!! ");
//刷新
writer.flush();
/** 接收内容
* 形式: 缓存字符流 <- 字符流 <- 字节流
*/
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("客户端 : " + reader.readLine());
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/*
服务器已创建!
等待客户端连接。。。
一个用户连接!
客户端 : 好久不见!
*/
客户端:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class MyClient {
/**
* writer - 输出内容(文本输出流)
* reader - 接收用户信息(缓冲字符输入流)
* socket - 套接字(进行与客户端数据交互的渠道)
*/
private PrintWriter writer = null;
private BufferedReader reader = null;
private Socket socket = null;
private void clientStart() {
try {
socket = new Socket("127.0.0.1" , 8848);
writer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//客户端我写的个简写版的
printReceiving();
printAndSend("好久不见!");
} catch (IOException e) {
e.printStackTrace();
}
}
//接收内容
private void printReceiving() {
try {
System.out.println("服务端 : " + reader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
//发送内容
private void printAndSend(String scr) {
writer.println(scr);
writer.flush();
}
public static void main(String[] args) {
new MyClient().clientStart();
}
}
/*
服务端 : 欢迎连接本服务器!!!
*/
# UDP信息发放
发送端:
package kkb;
import java.io.IOException;
import java.net.*;
// UDP 广播 (发送方
public class MyBroadcast extends Thread {
/**
* data - 数据包
* socket - 数据包套接字
* portPacket - 数据包标签 端口号
* ipPacket - 数据包标签 IP
*/
private DatagramPacket data = null;
private DatagramSocket socket = null;
private int portPacket = 4399;
private InetAddress ipPacket = null;
public MyBroadcast() {
try {
ipPacket = InetAddress.getByName("127.0.0.1");
socket = new DatagramSocket();
System.out.println("UDP服务器已启动!");
} catch (SocketException | UnknownHostException e) {
e.printStackTrace();
}
}
@Override
public void run() {
printAndSend("欢迎来到 柏竹 FM广播间!!!");
while(true){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
printAndSend("今天天气是晴天!");
}
}
//广播内容
private void printAndSend(String src) {
byte[] bt = src.getBytes();
data = new DatagramPacket(bt , bt.length , ipPacket , portPacket);
try {
socket.send(data);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new MyBroadcast().start();
}
}
/*
*
* UDP服务器已启动!
*
* */
接收端:
package kkb;
// UDP 广播 (接收方
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class MyReceiveUil extends Thread{
/**
* data - 数据包
* socket - 数据包套接字
*/
private DatagramSocket socket = null;
private int port= 4399;
public MyReceiveUil(){
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
printData(getData());
}
}
private void printData(DatagramPacket data) {
try {
socket.receive(data);
} catch (IOException e) {
e.printStackTrace();
}
String scr = new String(data.getData() , 0 , data.getLength());
System.out.println(scr);
}
private DatagramPacket getData() {
byte[] bt = new byte[1024];
return new DatagramPacket(bt , bt.length);
}
public static void main(String[] args) {
new MyReceiveUil().start();
}
}
/*
欢迎来到 柏竹 FM广播间!!!
今天天气是晴天!
今天天气是晴天!
·····
*/
# 组播发放
发送报:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
//UDP广播 (发送报
public class UdpBroadcastTest extends Thread{
//广播类
private MulticastSocket socket;
//端口号
private int port = 2233;
//广播组IP
private InetAddress group;
public UdpBroadcastTest(){
try {
//给定IP地址
group = InetAddress.getByName("224.233.2.1");
socket = new MulticastSocket(port);
socket.joinGroup(group);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
//数据包
DatagramPacket packet;
while (true) {
SimpleDateFormat date = new SimpleDateFormat("HH:mm:ss");
String scr = "["+ date.format(new Date())+ "] 今天天气晴天!!";
byte[] bt = scr.getBytes();
packet = new DatagramPacket(bt , bt.length , group , port);
try {
socket.send(packet);
Thread.sleep(2000);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new UdpBroadcastTest().start();
}
}
/*运行结果为窗体形式*/
接收报:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
//UDP广播 (接收报
public class UdpReceiveTest extends JFrame implements Runnable,ActionListener {
//初始化数值
//广播类
private MulticastSocket socket = null;
//广播地址组
private InetAddress group = null;
private int port = 2233;
private JButton
ince = new JButton("开始接收"),
stop = new JButton("停止接收");
//文本域
private JTextArea
inceAr = new JTextArea(10,10),
inced = new JTextArea(10,10);
private JScrollPane
jspinceAr = null,
jspinced = null;
private Thread t;
//广播关闭 (开关
private boolean ReceiveSwitch = false;
private Container c = getContentPane();
public UdpReceiveTest(){
super("广播数据报");
t = new Thread(this);
setDefaultCloseOperation(3);
setBounds(400 , 300 , 500 , 380);
//聚集作用的面板(按钮
ince.addActionListener(this);
stop.addActionListener(this);
JPanel north = new JPanel();
north.add(ince);
north.add(stop);
c.add(north , BorderLayout.NORTH);
//聚集作用的面板(文本域
inceAr.setForeground(Color.blue);
inceAr.setFont(new Font("微软雅黑",Font.PLAIN,16));
inced.setFont(new Font("微软雅黑",Font.PLAIN,16));
//自动换行+换行不断字
inceAr.setLineWrap(true);
inced.setLineWrap(true);
inceAr.setWrapStyleWord(true);
inced.setWrapStyleWord(true);
//文本域 改至滚动面板
jspinceAr = new JScrollPane(inceAr);
jspinced = new JScrollPane(inced);
JPanel center = new JPanel();
center.add(jspinceAr);
center.add(jspinced);
c.add(center , BorderLayout.CENTER);
//验证所有组件 (刷新作用
c.validate();
try {
group = InetAddress.getByName("224.233.2.1");
socket = new MulticastSocket(port);
socket.joinGroup(group);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
setVisible(true);
}
@Override
public void run() {
while (true){
byte data[] = new byte[1024];
DatagramPacket packet = null;
String scr = null;
packet = new DatagramPacket(data , data.length , group , port);
try {
//从此套接字接收数据报包
socket.receive(packet);
//获取数据
scr = new String(packet.getData() , 0 , packet.getLength());
inceAr.setText("正在接收广播内容:\n"+scr);
inced.append(scr+"\n");
} catch (IOException e) {
e.printStackTrace();
}
if(ReceiveSwitch){
break;
}
}
}
@Override
public void actionPerformed(ActionEvent e){
//if点击开始
if(e.getSource() == ince){
ince.setBackground(Color.blue);
stop.setBackground(Color.yellow);
//判断线程是否已创建
if(!(t.isAlive())){
t = new Thread(this);
}
t.start();
ReceiveSwitch = false;
}
//if点击停止
if(e.getSource() == stop){
stop.setBackground(Color.red);
ince.setBackground(Color.white);
ReceiveSwitch = true;
}
}
public static void main(String[] args) {
new UdpReceiveTest();
}
}
/*运行结果为窗体形式*/
# TCP多线程访问
服务端:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import static java.util.concurrent.Executors.*;
public class MyServer extends Thread{
private ServerSocket server = null;
private Socket socket = null;
private ExecutorService service = null;
private int count = 0;
public MyServer() {
try {
server = new ServerSocket(9959);
service = newCachedThreadPool();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("启动...");
}
@Override
public void run() {
while (true){
try {
socket = server.accept();
System.out.println("一个客户连接");
count++;
} catch (IOException e) {
e.printStackTrace();
}
service.execute(() -> {
BufferedReader reader = null;
PrintWriter writer = null;
int n = count;
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
while (true){
try {
System.out.println(" 家长" + n + " : "+reader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
public static void main(String[] args) {
new MyServer().start();
}
}
/*
启动...
一个客户连接
家长1 : 你哪里人啊 !?
一个客户连接
家长2 : 你多大啦 !?
一个客户连接
家长3 : 你成绩多少分 !?
家长2 : 你多大啦 !?
家长1 : 你哪里人啊 !?
家长2 : 你多大啦 !?
家长3 : 你成绩多少分 !?
。。。。。。
*/
客户端 1:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
public class Client1 extends Thread{
private Socket socket = null;
private PrintWriter writer = null;
public Client1() {
try {
socket = new Socket("127.0.0.1" , 9959);
writer = new PrintWriter(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
writer.println("你哪里人啊 !?");
writer.flush();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("out");
}
}
public static void main(String[] args) {
new Client1().start();
}
}
客户端 2:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
public class Client2 extends Thread{
private Socket socket = null;
private PrintWriter writer = null;
public Client2() {
try {
socket = new Socket("127.0.0.1" , 9959);
writer = new PrintWriter(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
writer.println("你多大啦 !?");
writer.flush();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("out");
}
}
public static void main(String[] args) {
new Client2().start();
}
}
客户端 3:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
public class Client3 extends Thread{
private Socket socket = null;
private PrintWriter writer = null;
public Client3() {
try {
socket = new Socket("127.0.0.1" , 9959);
writer = new PrintWriter(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
writer.println("你成绩多少分 !?");
writer.flush();
try {
Thread.sleep(12000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("out");
}
}
public static void main(String[] args) {
new Client3().start();
}
}