文章目录
网络编程
学习本节网络编程,最好配合Java网络编程概述(IP和端口号、网络通讯协议、TCP和UDP协议的概述及其区别)一起学习,这样能够达到理论与实际相结合,可以对网络编程由一个更加全面的学习。
Socket套接字
概述
1、利用套接字(Socket)开发网络应用早已被广泛的采用,以至于成为事实上的标准。
2、通信的两端都要有套接字(Socket),是两台机器间通信的端点。
3、网络通信其实就是Socket之间的通信。
4、Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
5、通常情况下主动发其通信的应用程序属于客户端,等待通信请求的是服务端。
Socket中的常用方法
返回值 | 方法名 | 功能 |
---|---|---|
InetAddress | getLocalAddress() | 返回对方Socket中的IP的InetAddress对象 |
int | getLocalPort() | 返回本地Socket中的端口号 |
InetAddress | getInetAddress() | 返回对方Socket中的IP地址 |
int | getPort() | 返回对方Socket中的端口号 |
void | close() | 关闭Socket |
InputStream | getInputStream() | 获取与Socket相关联的字节输入流,用于读数据 |
OutputStream | getOutputStream() | 获取与Socket相关联的字节输出流,用于写数据 |
Socket | accept() | 监听客户端的连接请求,返回与该客户端通信的Socket对象 |
void | close() | 关闭监听Socket |
InetAddress | getInetAddress() | 返回此服务器套接字的本地地址 |
int | getLocalPort() | 返回此套接字在其上监听的端口号 |
SocketAddress | getLocalSocketAddress() | 返回此套接字绑定的端点的地址 |
TCP网络通信
客户端
工作过程
客户端Socket的工作过程包含以下四个基本步骤
**1、创建Socket:**根据指定服务端的IP地址或端口号构造Socket类对象。若服务器端响应,则建立客户端到服务器的通信线路。若连接失败,会出现异常。
**2、打开连接到Socket的输入/出流:**使用getInputStream()方法获得输入流,使用getOutputStream()方法获得输出流,进行数据传输。
**3、按照一定的协议对Socket进行读/写操作:**通过输入流读取服务器放入线路的信息(但不能读取子集放入线路的信息),通过输出流将信息写入进程。
**4、关闭Socket:**断开客户端到服务器的连接,释放线路。
创建客户端
1、客户端程序可以使用Socket类创建对象,创建的同时会自动向服务器方发起连接。Socket的构造方法是:
(1)Socket(String host,int port):向服务器(域名host,端口号port)发起TCP连接,若成功,则创建Socket对象,否则抛出异常。
(2)Socket(InetAddress address,int port):根据InetAddress对象所代表的IP地址以及端口号port发起连接。
2、客户端建立socketAtClient对象的过程就是像服务器发送套接字请求。
代码示例——创建客户端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
/*这是一个程序入口*/
public static void main(String[] args) throws IOException {
/*创建一个客户端,会抛出异常,本地回环IP,端口号9999*/
Socket client = new Socket("localhost", 9999);
System.out.println("已连接");
/*获取一个输出流,向服务器发送一个消息*/
OutputStream outputStream = client.getOutputStream();
outputStream.write("服务器,你好!".getBytes());
/*获取一个输入流,接收来自服务器得消息*/
InputStream inputStream = client.getInputStream();
byte[] bytes = new byte[1024];
int length = inputStream.read(bytes);
System.out.println(new String(bytes, 0, length));
/*关闭输入输出流和socket*/
outputStream.close();
inputStream.close();
client.close();
}
}
服务器
工作过程
服务器程序的工作过程包含以下四个基本步骤
**1、调用ServerSocket(int port):**创建一个服务器端套接字,并绑定到指定端口上。用于监听客户端的请求。
**2、调用accept():**监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字对象。
**3、调用Socket类对象的getOutputStream()和getInputStream():**获取输入输出流,开始网络数据的发送和接收。
**4、关闭ServerSocket和Socket对象:**客户端访问结束,关闭通信套接字。
创建服务器
服务器建立ServerSocket对象,ServerSocket对象负责等待客户端请求建立套接字连接,类似于邮局某个窗口的业务员。也就是说,**服务器必须事先建立一个等待客户请求建立套接字连接的ServerSocket对象,**所谓的“接收”客户端的套接字请求,就是accept()方法会返回一个Socket对象。
代码示例——建立服务器
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
/*这是一个程序入口*/
public static void main(String[] args) throws IOException {
/*创建一个服务器端*/
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("等待客户端连接...");
/*监听客户端*/
Socket server = serverSocket.accept();
System.out.println("已连接");
/*接收客户端的消息*/
InputStream inputStream = server.getInputStream();
byte[] bytes = new byte[1024];
int length = inputStream.read(bytes);
System.out.println(new String(bytes, 0, length));
/*向客户端发送消息*/
OutputStream outputStream = server.getOutputStream();
outputStream.write("客户端,你好!".getBytes());
/*关闭输入输出流服务器*/
inputStream.close();
outputStream.close();
server.close();
serverSocket.close();
}
}
TCP实现双方连续交互
代码示例——服务器与客户端的连续交互——服务器
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class ServerDemo1 {
/*这是一个程序入口*/
public static void main(String[] args) throws IOException {
/*创建一个服务器,保持持续开启不断开*/
ServerSocket serverSocket = new ServerSocket(9898);
System.out.println("等待客户端连接.....");
/*监听客户端连接*/
Socket server = serverSocket.accept();
System.out.println("客户端连接成功!");
/*创建输入输出流*/
OutputStream outputStream = null;
InputStream inputStream = null;
Scanner data = new Scanner(System.in);
while(true){
inputStream = server.getInputStream();
byte[] bytes = new byte[1024];
int length = inputStream.read(bytes);
System.out.println("小客:"+new String(bytes,0,length));
outputStream = server.getOutputStream();
String msg = data.next();
outputStream.write(msg.getBytes());
}
}
}
代码示例——服务器与客户端的连续交互——客户端
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class ClientDemo1 {
/*这是一个程序入口*/
public static void main(String[] args) throws IOException {
/*创建一个客户端*/
Socket client = new Socket("127.0.0.1", 9898);
System.out.println("服务器连接成功!");
/*创建输入输出流*/
OutputStream outputStream = null;
InputStream inputStream = null;
System.out.println("请输入您想询问小服的问题:");
Scanner data = new Scanner(System.in);
while (true) {
outputStream = client.getOutputStream();
String msg = data.next();
outputStream.write(msg.getBytes());
if (msg.equals("再见")){
break;
}
inputStream = client.getInputStream();
byte[] bytes = new byte[1024];
int length = inputStream.read(bytes);
System.out.println("小服:" + new String(bytes,0,length));
}
outputStream.close();
client.close();
}
}
UDP网络通信
概述
1、类 DatagramSocket 和 DatagramPacket 实现了基于UDP协议网络程序。
2、UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以送达。
3、DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
4、UDP协议中每个数据报都给出了完整的地址信息,因此无法建立发送方和接收方的连接。
5、UDP网络通信流程
(1)DatagramSocket 与 DatagramPacket;
(2)建立发送端和接收端;
(3)建立数据包;
(4)调用 Socket 的发送、接收方法;
(5)关闭 Socket。
6、发送端和接收端是两个独立运行的程序。
实现UDP网络通信
发送端
import java.io.IOException;
import java.net.*;
/*发送端*/
public class Send {
/*这是一个程序入口*/
public static void main(String[] args) throws IOException {
/*创建发送数据包的套接字*/
DatagramSocket socket = new DatagramSocket();
/*获取要发送的东西的字节数组*/
byte[] bytes = "接收端,你好!".getBytes();
/*
* 创建传送数据报的包,
* 指定一个InetAddress对象的IP地址InetAddress.getByName("127.0.0.1"),
* 和端口号9009
*/
DatagramPacket packet = new DatagramPacket(bytes, bytes.length,
InetAddress.getByName("127.0.0.1"),9009);
/*使用DatagramSocket发送*/
socket.send(packet);
/*关闭套接字*/
socket.close();
}
}
接收端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Receive {
/*这是一个程序入口*/
public static void main(String[] args) throws IOException {
/*创建接收数据包的套接字,指定端口号9009(指定监听的端口)*/
DatagramSocket socket = new DatagramSocket(9009);
/*创建一个装数据的字节数组*/
byte[] bytes = new byte[1024];
/*
* 创建一个接收数据报的包
* DatagramPacket(byte[] buf, int length)
* 构造一个 DatagramPacket用于接收长度的数据包 length
*/
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
/*使用DatagramSocket接收*/
socket.receive(packet);
/*将接收到包里数据报转化为字符串并输出*/
String msg = new String(packet.getData(), 0, packet.getLength());
System.out.println("发送端:" + msg);
socket.close();
}
}
UDP实现双方连续交互
所谓的发送端:(因为两端都是独立的程序)
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class SendDemo {
/*这是一个程序入口*/
public static void main(String[] args) throws IOException {
/*创建互相通信的Socket*/
DatagramSocket socket = new DatagramSocket(6666);
System.out.println("已完成连接...请输入");
Scanner data = new Scanner(System.in);
while(true){
/*发送消息*/
String msgSend = data.next();
byte[] bytes = msgSend.getBytes();
DatagramPacket packetSend = new DatagramPacket(bytes,0, bytes.length,
InetAddress.getByName("127.0.0.1"), 5656);
socket.send(packetSend);
if (msgSend.equals("再见")){
break;
}
/*接收消息*/
byte[] bytes1 = new byte[1024];
DatagramPacket packetReceive = new DatagramPacket(bytes1, 0,bytes1.length);
socket.receive(packetReceive);
String msgReceive = new String(packetReceive.getData(),0,packetReceive.getLength());
System.out.println("白云:"+msgReceive);
}
socket.close();
}
}
所谓的接收端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class ReceiveDemo {
/*这是一个程序入口*/
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(5656);
Scanner data = new Scanner(System.in);
while(true){
/*接收消息*/
byte[] bytes = new byte[1024];
DatagramPacket packetReceive = new DatagramPacket(bytes,0,bytes.length);
socket.receive(packetReceive);
String msgReceive = new String(packetReceive.getData(), 0, packetReceive.getLength());
System.out.println("黑土:" + msgReceive);
/*发送消息*/
String msgSend = data.next();
byte[] bytes1 = msgSend.getBytes();
DatagramPacket packetSend = new DatagramPacket(bytes1,0, bytes1.length,
InetAddress.getByName("localhost"), 6666);
socket.send(packetSend);
if (msgSend.equals("再见")){
break;
}
}
socket.close();
}
}