详细介绍:java基础--网络编程(13)

一,java网络编程中的常用类

1.InetAddress的使用

作用:封装计算机的IP地址和域名

特点:这个类没有构造方法。如果要得到对象,只能通过getLocalHost()、getByName()等静态方法创建对象

01.获取本机信息

获取本机信息需要使用getLocalHost方法创建InetAddress 对象。getLocalHost() 方法返回一个InetAddress对象,这个对象包含了本机的IP地址,计算机名等信息。

public class InetTest {
 public static void main(String[] args)throws Exception {
 //实例化InetAddress对象
InetAddress inetAddress = InetAddress.getLocalHost();
 //返回当前计算机的IP地址
System.out.println(inetAddress.getHostAddress());
 //返回当前计算机名
System.out.println(inetAddress.getHostName());
 }
 }

02。根据域名获取计算机信息

根据域名获取计算机信息时需要使用getByName(“域名”)方法创建InetAddress对象

public class InetTest2 {
 public static void main(String[] args)throws Exception {
 InetAddress inetAddress =
 InetAddress.getByName("www.baidu.com");
 System.out.println(inetAddress.getHostAddress());
 System.out.println(inetAddress.getHostName());
 }
 }

03.根据IP获取计算机信息

根据IP地址获取计算机信息时需要使用getByName(“IP”)方法创建InetAddress 对象。

public class InetTest3 {
 public static void main(String[] args)throws Exception {
 InetAddress inetAddress =
 InetAddress.getByName("39.156.66.14");
 System.out.println(inetAddress.getHostAddress());
 System.out.println(inetAddress.getHostName());
 }
 }

2.InetSocketAddress的使用

作用:包含IP和端口信息,常用于Socket通信。此类实现 IP 套接字地址(IP 地址 + 端口号),不依赖任何协议。

InetSocketAddress 相比较 InetAddress 多了一个端口号,端口的作用:一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等,这些服务完全可以通 过1个IP地址来实现。

那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP 地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区分不同的服务的

public class InetSocketTest {
 public static void main(String[] args) {
 InetSocketAddress inetSocketAddress = new
 InetSocketAddress("www.baidu.com",80);
 System.out.println(inetSocketAddress.getAddress().getHostAddress(
 ));
 System.out.println(inetSocketAddress.getHostName());
 }
 }

3.URL类的使用

IP 地址标识了Internet上唯一的计算机,而URL则标识了这些计算机上的资源。URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。

为了方便程序员编程,JDK中提供了URL类,该类的全名是java.net.URL,有了这样 一个类,就可以使用它的各种方法来对URL对象进行分割、合并等处理。

public class UrlTest {
 public static void main(String[] args)throws Exception {
 URL url = new
 URL("http://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&rsv_idx=1&tn=ba
 idu&wd=itbz");
 System.out.println("获取与此URL相关联协议的默认端口:"+url.getDefaultPort());
 System.out.println("访问资源:"+url.getFile());
 System.out.println("主机名"+url.getHost());
 System.out.println("访问资源路径:"+url.getPath());
 System.out.println("协议:"+url.getProtocol());
 System.out.println("参数部分:"+url.getQuery());
 }
 }

二,TCP通信的实现

1.TCP通信介绍

前边我们提到TCP协议是面向连接的协议,在通信时客户端与服务器端必须建立连接。 在网络通信中,第一次主动发起通信的程序被称作客户端(Client)程序,简称客户端,而在第一次通信中等待连接的程序被称作服务器端(Server)程序,简称服务器。一旦通信建立,则客户端和服务器端完全一样,没有本质的区别。

“请求-响应”模式:

Socket类:发送TCP消息。

ServerSocket类:创建服务器。

套接字Socket是一种进程间的数据交换机制。这些进程既可以在同一机器上,也可以在通过网络连接的不同机器上。换句话说,套接字起到通信端点的作用。

单个套接字是一个端点,而一对套接字则构成一个双向通信信道,使非关联进程可以在本地或通过网络进行数据交换。一旦建立套接字连接,数据即可在相同或不同的系统中双向或单向发送,直到其中一个端点关闭连接。套接字与主机地址和端口地址相关联。主机地址就是客户端或服务器程序所在的主机的IP地址。端口地址是指客户端或服务器程序使用的主机的通信端口。

在客户端和服务器中,分别创建独立的Socket,并通过Socket的属性,将两个Socket 进行连接,这样,客户端和服务器通过套接字所建立的连接使用输入输出流进行通信。

TCP/IP 套接字是最可靠的双向流协议,使用TCP/IP可以发送任意数量的数据。

实际上,套接字只是计算机上已编号的端口。如果发送方和接收方计算机确定好端口,他们就可以通信了。

客户端与服务器端的通信关系图:

TCP/IP通信连接的简单过程:

位于A计算机上的TCP/IP软件向B计算机发送包含端口号的消息,B计算机的TCP/IP 软件接收该消息,并进行检查,查看是否有它知道的程序正在该端口上接收消息。如果有,他就将该消息交给这个程序。

要使程序有效地运行,就必须有一个客户端和一个服务器。

通过Socket的编程顺序:

1. 创建服务器ServerSocket,在创建时,定义ServerSocket的监听端口(在这个端口接收客户端发来的消息)。

2.  ServerSocket 调用 accept()方法,使之处于阻塞状态。

3.创建客户端Socket,并设置服务器的IP及端口。

4.客户端发出连接请求,建立连接。

5.分别取得服务器和客户端Socket的InputStream和OutputStream。

6.利用Socket和ServerSocket 进行数据传输。

7。关闭流及Socket。

2.入门案例

01。创建服务端

public class BasicSocketServer {
 public static void main(String[] args) {
 Socket socket = null;
 BufferedReader br = null;
 try {
 ServerSocket serverSocket = new ServerSocket(8888);
 System.out.println("服务器启动等待监听。。。。");
 //开启端口的监听
socket = serverSocket.accept();
 //读取客户端发送的消息
br = new BufferedReader(new
 InputStreamReader(socket.getInputStream()));
 System.out.println(br.readLine());
 } catch (IOException e) {
 e.printStackTrace();
 }finally {
 if(br != null){
 try {
 br.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if (socket !=null){
 try {
 socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }

02.创建客户端

public class BasicSocketClient {
 public static void main(String[] args) {
 Socket socket = null;
 PrintWriter pw= null;
 try {
 //创建Socket对象,两个参数:1,服务端的IP地址,2,服务端所监听的端口
socket = new Socket("127.0.0.1",8888);
 pw = new PrintWriter(socket.getOutputStream());
 pw.println("服务端您好!");
 pw.flush();
 } catch (IOException e) {
 e.printStackTrace();
 }finally {
 if(pw != null){
 pw.close();
 }
 if(socket !=null){
 try {
 socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }

3.TCP单向通信

单向通信是指通信双方中,一方固定为发送端,一方则固定为接收端。

01.创建服务端

public class OneWaySocketServer {
 public static void main(String[] args) {
 Socket socket = null;
BufferedReader br = null;
 PrintWriter pw = null;
 try{
 ServerSocket serverSocket = new ServerSocket(8888);
 System.out.println("服务端启动,开始监听。。。。。");
 socket = serverSocket.accept();
 System.out.println("连接成功!");
 //读取客户端发送的消息
br = new BufferedReader(new
 InputStreamReader(socket.getInputStream()));
 //向客户端写回消息的流对象
pw = new PrintWriter(socket.getOutputStream());
 while(true){
 String str = br.readLine();
 System.out.println("客户端说:"+str);
 if("exit".equals(str)){
 break;
 }
 pw.println(str);
 pw.flush();
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(br != null){
 try {
 br.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(pw != null){
 pw.close();
 }
 if(socket != null){
 try {
 socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }

02.创建客户端

public class OneWaySocketClient {
 public static void main(String[] args) {
 Socket socket = null;
 Scanner scanner = null;
 PrintWriter pw = null;
 BufferedReader br = null;
 try{
 socket = new Socket("127.0.0.1",8888);
 //创建键盘输入对象
scanner = new Scanner(System.in);
 //创建向服务端输出消息的流对象
pw = new PrintWriter(socket.getOutputStream());
 //创建读取服务端返回消息的流对象
br = new BufferedReader(new
 InputStreamReader(socket.getInputStream()));
 while(true){
 //通过键盘输入获取需要向服务端发送的消息
String str = scanner.nextLine();
 //将消息发送到服务端
pw.println(str);
 pw.flush();
 if("exit".equals(str)){
 break;
 }
 //读取服务端返回的消息
String serverInput = br.readLine();
 System.out.println("服务端返回的:"+serverInput);
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(scanner != null){
 scanner.close();
 }
 if(br != null){
 try {
 br.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(pw != null){
 pw.close();
 }
 if(socket != null){
 try {
 socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }

4.TCP双向通信

双向通信是指通信双方中,任何一方都可为发送端,任何一方都可为接收端。

01.创建服务端

public class TwoWaySocketServer {
 public static void main(String[] args) {
 ServerSocket serverSocket = null;
 Socket socket = null;
 BufferedReader br = null;
 Scanner scanner = null;
 PrintWriter pw = null;
 try{
 serverSocket = new ServerSocket(8888);
System.out.println("服务端启动!监听端口8888。。。。");
 socket = serverSocket.accept();
 //创建从客户端读取消息的流对象
br = new BufferedReader(new
 InputStreamReader(socket.getInputStream()));
 //创建键盘输入对象
scanner = new Scanner(System.in);
 //创建向客户端发送消息的输出流对象
pw = new PrintWriter(socket.getOutputStream());
 while(true){
 //读取客户端发送的消息
String str = br.readLine();
 System.out.println("客户端说:"+str);
 String keyInput = scanner.nextLine();
 //发送到客户端
pw.println(keyInput);
 pw.flush();
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(serverSocket != null){
 try {
 serverSocket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(socket != null){
 try {
 socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(br != null){
 try {
 br.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(scanner != null){
 scanner.close();
 }
 if(pw != null){
 pw.close();
 }
 }
 }
 }

02.创建客户端

public class TwoWaySocketClient {
 public static void main(String[] args) {
 Socket socket = null;
 Scanner scanner = null;
 PrintWriter pw = null;
 BufferedReader br = null;
 try{
 socket = new Socket("127.0.0.1",8888);
 //键盘输入对象
scanner = new Scanner(System.in);
 //创建向服务端发送消息的流对象
pw = new PrintWriter(socket.getOutputStream());
 //创建读取服务端发送消息的流对象
br = new BufferedReader(new
 InputStreamReader(socket.getInputStream()));
 while(true){
 String keyInput = scanner.nextLine();
 pw.println(keyInput);
 pw.flush();
 String input = br.readLine();
 System.out.println("服务端说:"+input);
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(socket!= null){
 try {
 socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(pw != null){
 pw.close();
 }
 if(br != null){
 try {
 br.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(scanner != null){
 scanner.close();
 }
 }
 }
 }

5.创建点对点的聊天应用

01.创建服务端

/**
 *发送消息线程
*/
 class Send extends Thread{
 private Socket socket;
 public Send(Socket socket){
 this.socket = socket;
 }
 @Override
 public void run() {
 this.sendMsg();
}
 /**
 * 发送消息
*/
 private void sendMsg(){
 Scanner scanner = null;
 PrintWriter pw = null;
 try{
 //创建Scanner对象
scanner = new Scanner(System.in);
 //创建向对方输出消息的流对象
pw = new PrintWriter(this.socket.getOutputStream());
 while(true){
 String msg = scanner.nextLine();
 pw.println(msg);
 pw.flush();
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally {
 if(scanner != null ){
 scanner.close();
 }
 if(pw != null){
 pw.close();
 }
 if(this.socket != null){
 try {
 this.socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }
 /**
 * 接收消息的线程
*/
 24
class Receive extends Thread{
 private Socket socket;
 public Receive(Socket socket){
 this.socket = socket;
 }
 @Override
 public void run() {
 this.receiveMsg();
 }
 /**
 * 用于接收对方消息的方法
*/
 private void receiveMsg(){
 BufferedReader br = null;
 try{
 //创建用于接收对方发送消息的流对象
br = new BufferedReader(new
 InputStreamReader(this.socket.getInputStream()));
 while(true){
 String msg = br.readLine();
 System.out.println("他说:"+msg);
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(br != null){
 try {
 br.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }
 public class ChatSocketServer {
 public static void main(String[] args) {
 ServerSocket serverSocket = null;
 try{
 serverSocket = new ServerSocket(8888);
 System.out.println("服务端启动,等待连接。。。。。");
 Socket socket = serverSocket.accept();
 System.out.println("连接成功!");
 new Send(socket).start();
 new Receive(socket).start();
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(serverSocket != null){
 try {
 serverSocket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }

02.创建客户端

/**
 *用于发送消息的线程类
*/
 class ClientSend extends Thread{
 private Socket socket;
 public ClientSend(Socket socket){
 this.socket = socket;
 }
 @Override
 public void run() {
 this.sendMsg();
 }
 /**
 *发送消息
*/
 private void sendMsg(){
 Scanner scanner = null;
PrintWriter pw = null;
 try{
 //创建Scanner对象
scanner = new Scanner(System.in);
 //创建向对方输出消息的流对象
pw = new PrintWriter(this.socket.getOutputStream());
 while(true){
 String msg = scanner.nextLine();
 pw.println(msg);
 pw.flush();
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally {
 if(scanner != null ){
 scanner.close();
 }
 if(pw != null){
 pw.close();
 }
 if(this.socket != null){
 try {
 this.socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }
 /**
 * 用于接收消息的线程类
*/
 class ClientReceive extends Thread{
 private Socket socket;
 public ClientReceive(Socket socket){
 this.socket = socket;
 }
 @Override
 public void run() {
 this.receiveMsg();
 27
}
 /**
 * 用于接收对方消息的方法
*/
 private void receiveMsg(){
 BufferedReader br = null;
 try{
 //创建用于接收对方发送消息的流对象
br = new BufferedReader(new
 InputStreamReader(this.socket.getInputStream()));
 while(true){
 String msg = br.readLine();
 System.out.println("他说:"+msg);
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(br != null){
 try {
 br.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }
 public class ChatSocketClient {
 public static void main(String[] args) {
 try {
 Socket socket = new Socket("127.0.0.1", 8888);
 System.out.println("连接成功!");
 new ClientSend(socket).start();
 new ClientReceive(socket).start();
 }catch(Exception e){
 e.printStackTrace();
 }
 }
 }
/**
 * 发送消息线程
*/
 class Send1 extends Thread{
 private Socket socket;
 private Scanner scanner;
 public Send1(Socket socket,Scanner scanner){
 this.socket = socket;
 this.scanner = scanner;
 }
 @Override
 public void run() {
 this.sendMsg();
 }
 /**
 * 发送消息
*/
 private void sendMsg(){
 PrintWriter pw = null;
 try{
 //创建向对方输出消息的流对象
pw = new PrintWriter(this.socket.getOutputStream());
 while(true){
 String msg = scanner.nextLine();
 pw.println(msg);
 pw.flush();
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally {
 if(scanner != null ){
 scanner.close();
 }
 if(pw != null){
 pw.close();
 }
if(this.socket != null){
 try {
 this.socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }
 /**
 * 接收消息的线程
*/
 class Receive1 extends Thread{
 private Socket socket;
 public Receive1(Socket socket){
 this.socket = socket;
 }
 @Override
 public void run() {
 this.receiveMsg();
 }
 /**
 * 用于接收对方消息的方法
*/
 private void receiveMsg(){
 BufferedReader br = null;
 try{
 //创建用于接收对方发送消息的流对象
br = new BufferedReader(new
 InputStreamReader(this.socket.getInputStream()));
 while(true){
 String msg = br.readLine();
 System.out.println("他说:"+msg);
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(br != null){
try {
 br.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(this.socket != null){
 try {
 this.socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }
 public class GoodTCP {
 public static void main(String[] args) {
 Scanner scanner = null;
 ServerSocket serverSocket = null;
 Socket socket = null;
 try{
 scanner = new Scanner(System.in);
 System.out.println("请输入:server, 或者:
,");
 String str = scanner.nextLine();
 String[] arr = str.split(",");
 if("server".equals(arr[0])){
 //启动服务端
System.out.println("TCP Server Listen at
 "+arr[1]+" .....");
 serverSocket = new
 ServerSocket(Integer.parseInt(arr[1]));
 socket = serverSocket.accept();
 System.out.println("连接成功!");
 }else{
 //启动客户端
socket = new Socket(arr[0],Integer.parseInt(arr[1]));
System.out.println("连接成功!");
 }
 //启动发送消息的线程
new Send1(socket,scanner).start();
 //启动接收消息的线程
new Receive1(socket).start();
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(serverSocket != null){
 try {
 serverSocket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }

03.优化点对点聊天应用

6.一对多应用

01.一对多应用设计

各socket 对间独立问答,互相间不需要传递信息

02.一对多问答型服务器

/**
 * 定义消息处理线程类
*/
 class Msg extends Thread{
 private Socket socket;
 public Msg(Socket socket){
 this.socket = socket;
 }
 @Override
 public void run() {
 this.msg();
 }
 private void msg(){
 BufferedReader br = null;
 PrintWriter pw = null;
 try{
 br = new BufferedReader(new
 InputStreamReader(this.socket.getInputStream()));
 pw = new PrintWriter(this.socket.getOutputStream());
 while(true){
 pw.println(br.readLine()+" [ok]");
 pw.flush();
 }
 }catch(Exception e){
 System.out.println(this.socket.getInetAddress()+" 断线了!");
 e.printStackTrace();
 }finally{
 if(br != null){
 try {
 br.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(pw != null){
 pw.close();
 }
 }
 }
 }
 public class EchoServer {
 public static void main(String[] args) {
 ServerSocket serverSocket = null;
 try{
 serverSocket = new ServerSocket(8888);
 while(true){
 Socket socket = serverSocket.accept();
 new Msg(socket).start();
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(serverSocket != null){
 try {
 serverSocket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }

03.一对多聊天服务器

001.服务器设计
0001.服务器的连接设计

0002,服务器的线程设计

04,创建一对多聊天服务应用

/**
 * 接收客户端消息的线程类
*/
 class ChatReceive extends Thread{
 private Socket socket;
 public ChatReceive(Socket socket){
 this.socket =socket;
 }
 @Override
 public void run() {
 this.receiveMsg();
 }
 /**
 * 实现接收客户端发送的消息
*/
 private void receiveMsg(){
 BufferedReader br = null;
 try{
 br = new BufferedReader(new
 InputStreamReader(this.socket.getInputStream()));
 while(true){
 String msg = br.readLine();
 synchronized ("abc"){
 //把读取到的数据写入公共数据区
ChatRoomServer.buf="["+this.socket.getInetAddress()+"] "+msg;
 //唤醒发送消息的线程对象。
"abc".notifyAll();
 }
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(br != null){
 try {
 br.close();
} catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(this.socket != null){
 try {
 this.socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }
 /**
 * 向客户端发送消息的线程类
*/
 class ChatSend extends Thread{
 private Socket socket;
 public ChatSend(Socket socket){
 this.socket = socket;
 }
 @Override
 public void run() {
 this.sendMsg();
 }
 /**
 * 将公共数据区的消息发送给客户端
*/
 private void sendMsg(){
 PrintWriter pw = null;
 try{
 pw = new PrintWriter(this.socket.getOutputStream());
 while(true){
 synchronized ("abc"){
 //让发送消息的线程处于等待状态
  "abc".wait();
 //将公共数据区中的消息发送给客户端
pw.println(ChatRoomServer.buf);
 pw.flush();
}
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(pw != null){
 pw.close();
 }
 if(this.socket != null){
 try {
 this.socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }
 public class ChatRoomServer {
 //定义公共数据区
public static String buf;
 public static void main(String[] args) {
 System.out.println("Chat Server Version 1.0");
 System.out.println("Listen at 8888.....");
 ServerSocket serverSocket =null;
 try{
 serverSocket = new ServerSocket(8888);
 while(true){
 Socket socket = serverSocket.accept();
 System.out.println("连接到:"+socket.getInetAddress());
 new ChatReceive(socket).start();
 new ChatSend(socket).start();
 }
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(serverSocket != null){
 try {
 serverSocket.close();
 } catch (IOException e) {
 e.printStackTrace();
}
 }
 }
 }
 }

三,UDP通信的实现

1.UDP通信介绍

UDP协议与之前讲到的TCP协议不同,是面向无连接的,双方不需要建立连接便可通信。UDP通信所发送的数据需要进行封包操作(使用DatagramPacket类),然后才能接收或发送(使用DatagramSocket类)。

DatagramPacket:数据容器(封包)的作用

此类表示数据报包。 数据报包用来实现将发送的数据进行封包处理的。

常用方法:

 DatagramPacket(byte[] buf, int length) :构造数据报包,用来指定长度为 length 的数据包。

 DatagramPacket(byte[] buf, int length, InetAddress address, int port) :构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。

 getAddress() :获取发送或接收方计算机的IP地址,此数据报将要发往该机器或者是从该机器接收到的。

 getData() :获取发送或接收的数据。

 setData(byte[] buf) :设置发送的数据。

DatagramSocket:用于发送或接收数据报包

当客户端要向服务端发送数据时,需要在客户端产生一个DatagramSocket对象,在服务端产生一个DatagramSocket对象。客户端的DatagramSocket将DatagramPacket 发送到网络上,然后被服务端的DatagramSocket接收。

常用方法:  DatagramSocket(int port) :创建数据报套接字并将其绑定到本地主机上的指定端口。

 send(DatagramPacket p) :从此套接字发送数据报包。

 receive(DatagramPacket p) :从此套接字接收数据报包。

 close() :关闭此数据报套接字。

 UDP通信编程基本步骤:

1. 创建服务器端的DatagramSocket,创建时,定义服务器端的监听端口。

2.创建客户端的DatagramSocket,创建时,定义客户端的监听端口。

3.在服务器端定义DatagramPacket对象,封装待接收的数据包。

4.客户端将数据报包发送出去。

5.服务器端接收数据报包。

2.入门案例

01.创建服务端

public class UDPTest {
 public static void main(String[] args) {
 DatagramSocket datagramSocket = null;
 try{
 //创建服务端接收数据的DatagramSocket对象
datagramSocket = new DatagramSocket(9999);
 //创建数据缓存区
byte[] b = new byte[1024];
 //创建数据报包对象
DatagramPacket dp =new DatagramPacket(b,b.length);
 //等待接收客户端所发送的数据
datagramSocket.receive(dp);
 String str = new String(dp.getData(),0,dp.getLength());
 System.out.println(str);
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(datagramSocket != null){
 datagramSocket.close();
 }
 }
 }
 }

02.创建客户端

public class UDPClient {
 public static void main(String[] args) {
 DatagramSocket ds =null;
 try {
 //消息需要进行类型转换,转换成字节数据类型。
 byte[] b = "北京尚学堂".getBytes();
 //创建数据报包装对象DatagramPacket
 DatagramPacket dp = new DatagramPacket(b, b.length, new
 InetSocketAddress("127.0.0.1", 9999));
 //创建数据发送对象DatagramSocket,需要指定消息的发送端口
ds = new DatagramSocket(8888);
 //发送消息
ds.send(dp);
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(ds != null){
 ds.close();
 }
 }
 }
 }

3.传递基本数据类型

01.创建服务端

public class BasicTypeServer {
 public static void main(String[] args) {
 DatagramSocket datagramSocket = null;
 DataInputStream ds = null;
 try{
 datagramSocket = new DatagramSocket(9999);
 byte[] buf = new byte[1024];
 DatagramPacket datagramPacket = new
 DatagramPacket(buf,buf.length);
 datagramSocket.receive(datagramPacket);
 //通过基本数据输入流对象获取传递的数据
ds = new DataInputStream(new
 ByteArrayInputStream(datagramPacket.getData()));
 System.out.println(ds.readLong());
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(datagramSocket != null){
 datagramSocket.close();
 }
 if(ds != null){
 try {
 ds.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }

02.创建客户端

public class BasicTypeClient {
 public static void main(String[] args) {
 long n = 2000L;
 ByteArrayOutputStream bos = null;
 DataOutputStream dos = null;
 DatagramSocket datagramSocket = null;
 try{
 bos = new ByteArrayOutputStream();
 dos = new DataOutputStream(bos);
 dos.writeLong(n);
 //将基本数据类型数据转换成字节数组类型
byte[] arr = bos.toByteArray();
 DatagramPacketdp=newDatagramPacket(arr,arr.length,new
 InetSocketAddress("127.0.0.1",9999));
 datagramSocket = new DatagramSocket(9000);
 datagramSocket.send(dp);
 }catch (Exception e){
 e.printStackTrace();
 }finally{
 if(bos != null ){
 try {
 bos.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(dos != null){
 try {
 dos.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(datagramSocket != null){
 datagramSocket.close();
 }
 }
 }
 }

4.传递自定义对象类型

01.创建Person类

/**
 *当该对象需要在网络上传输时,一定要实现Serializable接口
*/
 public class Person implements Serializable {
 private String name;
 private int age;
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public int getAge() {
 return age;
 }
 public void setAge(int age) {
 this.age = age;
 }
 @Override
 public String toString() {
 return "Person{" +
 "name='" + name + '\'' +
 ", age=" + age +
 '}';
 }
 }

02,。创建服务端

public class ObjectTypeServer {
 public static void main(String[] args) {
 DatagramSocket datagramSocket = null;
 ObjectInputStream objectInputStream = null;
 try{
 datagramSocket = new DatagramSocket(9999);
 byte[] b = new byte[1024];
 DatagramPacket dp = new DatagramPacket(b,b.length);
 datagramSocket.receive(dp);
 //对接收的内容做类型转换
objectInputStream = new ObjectInputStream(new
 ByteArrayInputStream(dp.getData()));
 System.out.println(objectInputStream.readObject());
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(datagramSocket != null){
 datagramSocket.close();
 }
 if(objectInputStream != null){
 try {
 objectInputStream.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
}

03.创建客户端

public class ObjectTypeClient {
 public static void main(String[] args) {
 DatagramSocket datagramSocket = null;
 ByteArrayOutputStream bos = null;
 ObjectOutputStream oos = null;
 try{
 Person p = new Person();
 p.setName("Oldlu");
 p.setAge(18);
 bos = new ByteArrayOutputStream();
 oos = new ObjectOutputStream(bos);
 oos.writeObject(p);
 byte[] arr = bos.toByteArray();
 DatagramPacket dp = new DatagramPacket(arr,arr.length,new
 InetSocketAddress("127.0.0.1",9999));
 datagramSocket = new DatagramSocket(8888);
 datagramSocket.send(dp);
 }catch(Exception e){
 e.printStackTrace();
 }finally{
 if(datagramSocket != null ){
 datagramSocket.close();
 }
 if(bos != null){
 try {
 bos.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if(oos != null){
 try {
 oos.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
}
 }
}

四,总结

 端口是虚拟的概念,并不是说在主机上真的有若干个端口。

 在www上,每一信息资源都有统一且唯一的地址,该地址就叫URL(Uniform Resource Locator),它是 www的统一资源定位符。

 TCP与UDP的区别

 TCP是面向连接的,传输数据安全,稳定,效率相对较低。

 UDP是面向无连接的,传输数据不安全,效率较高。

 Socket通信是一种基于TCP协议,建立稳定连接的点对点的通信。

 网络编程是由java.net包来提供网络功能。

 InetAddress:封装计算机的IP地址和DNS(没有端口信息!)。

 InetSocketAddress:包含IP和端口,常用于Socket通信。

 URL:以使用它的各种方法来对URL对象进行分割、合并等处理。

 基于TCP协议的Socket编程和通信

 “请求-响应”模式:

 Socket类:发送TCP消息。

 ServerSocket类:创建服务器。

 UDP通讯的实现

 DatagramSocket:用于发送或接收数据报包。

 常用方法:send()、receive()、 close()。

 DatagramPacket:数据容器(封包)的作用 

 常用方法:构造方法、getAddrress(获取发送或接收方计算机的IP地址)、 getData(获取发送或接收的数据)、setData(设置发送的数据)。

posted @ 2025-11-04 22:43  clnchanpin  阅读(19)  评论(0)    收藏  举报