InetAddress
类主要是用来得到所指定的网络地址InetAddress
类没有直接显式的构造函数。要生成一个InetAddress对象,必须运用一个可用的工厂方法。工厂方法(factory method
)仅是一个类中的静态方法返回一个该类实例的约定。这是在一个带有各种参数列表的重载构造函数中完成的,当持有惟一方法名时可使结果更清晰。InetAddress
有三个方法可以用来创建InetAddress
的实例
static InetAddress getLocalHost( ) throws UnknownHostException
static InetAddress getByName(String hostName) throws UnknownHostException
static InetAddress[ ] getAllByName(String hostName) throws UnknownHostException
boolean equals(Object other)
byte[ ] getAddress( )
String getHostAddress( )
String getHostName( )
int hashCode( )
boolean isMulticastAddress( )
String toString( )
Protocol://hostname:port/resourcename#anchor
,即 协议://主机名:端口/资源名#标记
URL urlBase=new URL("http://www. 263.net/");
URL url=new URL("http", "www.gamelan.com", "/pages/Gamelan.net. html");
URL gamelan=new URL("http", "www.gamelan.com", 80, "Pages/Gamelan.network.html");
public String getProtocol()
获取该URL的协议名。public String getHost()
获取该URL的主机名。public int getPort()
获取该URL的端口号,如果没有设置端口,返回-1。public String getFile()
获取该URL的文件名。public String getQuery()
获取该URL的查询信息。public String getPath()
获取该URL的路径。public String getAuthority()
获取该URL的权限信息。public String getUserInfo()
获得使用者的信息。public String getRef()
获得该URL的引用。URL类经常用于下载网络资源,URL通过构造函数(构造函数为URL地址)可以得到一个对象,该对象的openStream()方法可以得到InputStream对象,得到InputStream就可以把网站上的资源下载下来了
下面是一个实例,使用URL类下载某个网站上的一张图片并保存到本地。
import java.net.*;
import java.io.*;
public class TestURL
{
public static void main(String aregs[ ])throws Exception
{
URL url=new URL("http://images.sohu.com/uiue/sohu_logo/beijing2008/sohu.gif");
InputStream in=url.openStream();
FileOutputStream fout=new FileOutputStream(new File("sohu.gif"));
int a=0;
while(a>-1)
{
a=in.read();
fout.write(a);
}
}
}
运行成功后,在当前目录生成一个gif图片
String getHeaderField(String name)
InputStream getInputStream()
String getContentEncoding()
int getContentLength()
String getContentType()
long getDate()
使用InetAddress类的方法获取本地机的名称和IP地址
package com.ipaddress;
import java.net.*;
public class IPAddress {
public static void main(String[] args) {
try {
InetAddress inetAddress = InetAddress.getLocalHost();
String hostName = inetAddress.getHostName();
String hostAddress = inetAddress.getHostAddress();
System.out.println(hostName);
System.out.println(hostAddress);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
打印结果:
MacBook-Air.local
192.168.0.101
使用InetAddress类的方法获取网站www.csdn.net的IP地址,如果存在多个IP地址,要求全部返回。
package com.ipaddress;
import java.net.*;
public class CSDNAddress {
public static void main(String[] args) {
try {
InetAddress[] inetAddresses = InetAddress.getAllByName("www.csdn.net");
for (InetAddress inetAddress: inetAddresses) {
String hostName = inetAddress.getHostName();
String hostAddress = inetAddress.getHostAddress();
System.out.println(hostName + " " + hostAddress);
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
打印结果
www.csdn.net 39.106.226.142
使用URL类下载深圳大学首页http://www.szu.edu.cn,并统计下载得到网页文件的大小
package com.ipaddress;
import java.net.*;
import java.io.*;
public class SZUurl {
public static void main(String[] args) throws Exception {
URL url = new URL("http://www.szu.edu.cn");
URLConnection connection = url.openConnection();
int size = connection.getContentLength();
InputStream in = url.openStream();
FileOutputStream fout = new FileOutputStream(new File("szu.html"));
int a = 0;
while(a > -1) {
a = in.read();
fout.write(a);
}
fout.close();
System.out.println(size + "B");
}
}
打印结果
137 B
此时目录结构,可以看到szu.html
文件在此目录下
$ tree
.
├── Network.iml
├── out
│ └── production
│ └── Network
│ └── com
│ └── ipaddress
│ ├── CSDNAddress.class
│ ├── IPAddress.class
│ └── SZUurl.class
├── src
│ └── com
│ └── ipaddress
│ ├── CSDNAddress.java
│ ├── IPAddress.java
│ └── SZUurl.java
└── szu.html
8 directories, 8 files
cmd > netstat –na
可以查看本机的端口使用情况。
Socket是网络上运行的程序之间双向通信链路的最后终结点
IP与端口的组合得出一个套接字,可以完全分辨Internet上运行的程序
概述
Socket类的构造方法:
public Socket(String host, int port)
public Socket(InetAddress address, int port)
public Socket(String host, int port, InetAddress localAddr, int localPort)
//在指定的机器上的指定端口上运行
上述方法都将抛出例外IOException,程序中需要捕获处理。
Socket的常见方法:
//Socket的输入/输出流管理;抛出例外IOException。
public InputStream getInputStream()
public void shutdownInput()
public OutputStream getOutputStream()
public void shutdownOutput()
//关闭Socket
public void close() throws IOException
//设置/获取Socket数据:
public InetAddress getInetAddress() 返回此套接字链接的地址对象
public InetAddress getLocalAddress() 返回此套接字本地的地址对象
public int getPort() 返回此套接字链接地址的端口
上述方法都将抛出例外SocketException,程序中需要捕获处理。
ServerSocket类
构造方法:
public ServerSocket(int port)
public ServerSocket(int port, int backlog) //支持指定数目的连接
public ServerSocket(int port, int backlog, InetAddress bindAddr) //在指定的机器上运行
主要方法
public Socket accept():等待客户端的连接
public void close():关闭Socket
设置/获取Socket数据的方法
public InetAddress getInetAddress()
public int getLocalPort(), ...
Socket通信程序基本结构都一样,包括以下四个基本步骤:
通常,程序员的主要工作是针对所要完成的功能在第3步进行编程,第1、2、4步对所有的通信程序来说几乎都是一样的。
创建Socket
下面是一个典型的创建客户端Socket的代码:
try
{
Socket socket=new Socket("127.0.0.1",1432);
//127.0.0.1是TCP/IP协议中默认的本机地址
}catch(IOException e){
System.out.println("Error:"+e);
}
创建服务器应用程序
用于服务器的类和方法
ServerSocket类
创建服务器
构造函数的代码给出如下:
try {
server = new ServerSocket(1432);
//创建一个ServerSocket在端口1432监听客户请求
} catch (Exception e) {
System.out.println("can not listen to:" + e);
//出错,打印出错信息
}
System.out.println("Server started…");
this.start(); //启动线程
监听客户请求
ServerSocket对象通过accept()方法来监听客户的请求,如果接收到客户的请求,则产生一个Socket对象,并继续执行后面的代码;如果没有接收到客户请求,则产生一个错误信息。
Socket socket = null;
try {
socket = server.accept();
//使用accept()阻塞等待客户请求,有客户
//请求到来则产生一个Socket对象,并继续执行
} catch (Exception e) {
System.out.println("can not listen to:" + e);
//出错,打印出错信息
}
服务器的输入和输出流
服务器端用到了以下的输入和输出流:
``java
BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//由Socket对象得到输入流,并构造相应的BufferedReader对象
PrintWriter os = new PrintWriter(socket.getOutputStream());
//由Socket对象得到输出流,并构造PrintWriter对象
BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
//由系统标准输入设备构造BufferedReader对象
{
new Server();
}
完整的服务器程序
ObjectInputStream类
ObjectInputStream类中包含从持久的存储介质中读出类的对象的功能。持久的存储介质可以是磁盘或套接字。
这由ObjectInputStream类的readObject()方法来完成。readObject()方法的语法如下:
FileInputStream fp=new FileInputStream(“data.txt”);
ObjectInputStream istream = new ObjectInputStream(fp);
Date date = (Date)istream.readObject();
一般步骤
UDP通信是一种无连接的数据报通信。使用该协议,两个程序进行通信时不用建立连接;数据以独立的包为单位发送,包的容量限定在64KB以内;每个数据报需要有完整的收/发地址,可以随时进行收/发数据报,但不保证传送顺序和内容准确;数据报可能会被丢失、延误等。UDP通信是不可靠的通信,但通信速度较快,常常被应用在某些要求实时交互,准确性要求不高,但传输速度要求较高的场合(如视频会议系统等)。
Java中,基于UDP协议实现网络通信的类有三个:
用于表示通信数据的数据报类:DatagramPacket
用于进行端到端通信的类:DatagramSocket
用于广播通信的类:MulticastSocket。
用DatagramPacket类将数据打包,即创建数据包对象。
DatagramPacket(byte data[], int length, InetAddtress address,int port)
Address: 目标主机地址 Port:目标主机端口
如:
byte data[]=“近来好吗”.getByte();
InetAddress address=inetAddress.getByname(www.sina.com.cn);
DatagramPacket data_pack=new DatagramPacket(data,data.length,address,980);
注: data_pack常用方法:
用DatagramSocket类的构造方法DatagramSocket()创建一个对象,该对象负责发送数据包。例:
DatagramSocket mail_in=new DatagramSocket(int port);
注意:mail_in的主要方法:
利用Socket类和ServerSocket类编写一个C/S程序,实现C/S通信。
客户端向服务器端发送Time命令,服务器端接受到该字符串后将服务器端当前时间返回给客户端;客户端向服务器端发送Exit命令,服务器端向客户端返回“Bye”后退出。
编写完整程序;一个服务器端程序,一个客户端程序。服务器端和客户端都需要打印出接受到的消息和发出的命令。
下图为运行结果示例
Server.java
:
package com.csmode;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket;
DataOutputStream dataOutputStream;
DataInputStream dataInputStream;
System.out.println("Server Running ... ");
String time;
String goodbye = "Bye!";
String error = "No such Command!";
try {
//在端口号4096创建 serverSocket
serverSocket = new ServerSocket(4096);
} catch (IOException e) {
System.out.println("ServerSocket error");
e.printStackTrace();
}
try {
assert serverSocket != null;
socket = serverSocket.accept();
// 连接成功
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeUTF("服务器启动完毕\n创建客户连接\t\t");
// 标记什么时候退出
boolean flag = true;
while(flag) {
// 接收客户端发送过来的消息
dataInputStream = new DataInputStream(socket.getInputStream());
String str = dataInputStream.readUTF();
System.out.print(str + " : ");
if(str.equals("Time")) {
time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime());
dataOutputStream.writeUTF("服务器当前时间为:\t" + time);
System.out.println(time);
} else if (str.equals("Exit")) {
dataOutputStream.writeUTF(goodbye);
flag = false;
} else {
dataOutputStream.writeUTF(error);
}
}
} catch (IOException e) {
System.out.println("Socket data IO error");
e.printStackTrace();
}
}
}
Client.java
:
package com.csmode;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", 4096);
// 创建 Socket 管道
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
String string = dataInputStream.readUTF();
System.out.println(string);
while(true) {
// 输入命令
Scanner input = new Scanner(System.in);
String str = input.next();
dataOutputStream.writeUTF(str);
// 在服务器端传来的 数据
string = dataInputStream.readUTF();
System.out.println(string);
if(str.equals("Exit")) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
先启动Server.java
, 再启动Client.java
结果如下:
客户端:
服务器端:
编写一数据报通信程序,实现简单的聊天功能。
“聊天内容”和“输入文本”分别为当前聊天的历史信息和当前要传送出去的聊天文本。“确定”、“清空”、“退出”三个按钮分别实现发送当前聊天文本、清空当前聊天文本和退出系统的功能。
界面可参考如下格式
PID.java
package com.chattingroom;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
public class PID {
// 获取 PID
public static int getProcessID() {
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
return Integer.parseInt(runtimeMXBean.getName().split("@")[0]);
}
}
chat.java
package com.chattingroom;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class chat extends JFrame implements ActionListener, Runnable, KeyListener {
private TextArea textArea;
private JTextField sendText;
private JTextField ip;
private JTextField port;
private JButton buttonServer;
private JButton buttonClient;
private JButton send;
private JButton exit;
private JButton clear;
private Socket socket;
public void keyReleased(KeyEvent f) {
}
// 监听键盘输入
public void keyPressed(KeyEvent f) {
if (f.getKeyCode() == KeyEvent.VK_ENTER) {
PrintWriter printWriter = null;
try {
printWriter = new PrintWriter(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
String string = sendText.getText();
if (string == null)
return;
int pid = PID.getProcessID();
String User = ip.getText() + " : " + port.getText();
// 自己发的消息
textArea.append(User + " : " + pid + " says: " + "\n" + string + "\n");
// 对面发来的消息
String string3 = User + " : " + pid + " says: " + "\n" + string;
assert printWriter != null;
printWriter.println(string3);
printWriter.flush();
sendText.setText("");
}
}
public void keyTyped(KeyEvent f) {
}
// 轮询
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
String string = br.readLine();
if (string == null)
break;
textArea.append(string + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == buttonServer) {
server();
}
if (e.getSource() == buttonClient) {
client();
}
if (e.getSource() == send) {
doSend();
}
if (e.getSource() == exit) {
doExit();
}
if (e.getSource() == clear) {
doClear();
}
}
// 作为服务器启动
public void server() {
try {
ServerSocket server = new ServerSocket(Integer.parseInt(port.getText()));
socket = server.accept();
textArea.append("连接服务器成功!\n");
new Thread(this).start();
} catch (Exception e) {
textArea.append("服务器启动失败!\n");
}
}
// 作为客户端启动
public void client() {
try {
socket = new Socket(ip.getText(), Integer.parseInt(port.getText()));
textArea.append("连接服务器成功!\n");
new Thread(this).start();
} catch (Exception e) {
textArea.append("连接失败!\n");
}
}
// 发送消息
public void doSend() {
try {
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
String string = sendText.getText();
if (string == null)
return;
int pid = PID.getProcessID();
String User = ip.getText() + " : " + port.getText();
// 自己发的消息
textArea.append(User + " : " + pid + " says: " + "\n" + string + "\n");
// 对面发来的消息
String string3 = User + " : " + pid + " says: " + "\n" + string;
printWriter.println(string3);
printWriter.flush();
sendText.setText("");
} catch (Exception e) {
textArea.append("发送失败!\n");
}
}
// 清除聊天
public void doClear() {
textArea.setText("");
}
// 退出程序
public void doExit() {
System.exit(0);
}
// 连接键
public void addClient(JPanel panel) {
buttonClient = new JButton("连接");
buttonClient.setForeground(new Color(250, 131, 46));
buttonClient.setFont(new Font("宋体", Font.BOLD, 14));
panel.add(buttonClient);
}
// 监听键
public void addServer(JPanel panel) {
buttonServer = new JButton("监听");
buttonServer.setForeground(new Color(250, 131, 46));
buttonServer.setFont(new Font("宋体", Font.BOLD, 14));
panel.add(buttonServer);
}
// 清除键
public void addClear(JPanel panel) {
clear = new JButton("清除");
clear.setForeground(new Color(250, 131, 46));
clear.setFont(new Font("宋体", Font.BOLD, 14));
panel.add(clear);
}
// 退出键
public void addExit(JPanel panel) {
exit = new JButton("退出");
exit.setForeground(new Color(250, 131, 46));
exit.setFont(new Font("宋体", Font.BOLD, 14));
panel.add(exit);
}
// 设置 JPanel
public void setPanel(JPanel panel) {
panel.setLayout(new BorderLayout());
panel.add(ip, BorderLayout.WEST);
panel.setBackground(new Color(245, 161, 102));
sendText = new JTextField("");
panel.add(sendText, BorderLayout.CENTER);
send = new JButton("发送");
panel.add(send, BorderLayout.EAST);
}
// 设置按键监听
public void setListen() {
clear.addActionListener(this);
exit.addActionListener(this);
buttonServer.addActionListener(this);
buttonClient.addActionListener(this);
send.addActionListener(this);
sendText.addKeyListener(this);
}
public JPanel setJPanel1(Container container) {
JPanel panel = new JPanel();
container.add(panel, BorderLayout.NORTH);
panel.setBackground(new Color(231, 162, 112));
textArea = new TextArea();
container.add(textArea, BorderLayout.CENTER);
return panel;
}
public JPanel setJPanel2(Container container) {
JPanel panel = new JPanel();
container.add(panel, BorderLayout.SOUTH);
panel.setBackground(new Color(250, 180, 30));
textArea.setForeground(new Color(250, 131, 46));
return panel;
}
public void addButton(JPanel panel){
addServer(panel);
addClient(panel);
addClear(panel);
addExit(panel);
}
// 聊天界面
public chat(String IPAddress, String Port) {
this.setTitle("UDP聊天程序");
this.setBounds(200, 200, 500, 500);
Container container = this.getContentPane();
JPanel panel1 = setJPanel1(container);
JPanel panel2 = setJPanel2(container);
ip = new JTextField(IPAddress, 15);
port = new JTextField(Port, 4);
addButton(panel1);
setPanel(panel2);
setListen();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Run.java
package com.chattingroom;
public class Run {
public static void main(String[] args) {
new chat("127.0.0.1", "8192").setVisible(true);
}
}
目录结构如下:
$ tree chattingroom
chattingroom
├── PID.java
├── Run.java
└── chat.java
开启两个程序运行,效果如下:
左端输入123,右端输入456,结果如下:
利用Socket类和ServerSocket类,编写一个C/S程序,实现网络文件传输。
客户端向服务器端发送请求,服务器端当接受到客户端的请求之后,先向其传输文件名,当客户端接受完毕之后,向客户端传输文件
客户端连上服务器后接收传输文件,并进行改名(文件名可自行定义)存在本地。
编写完整程序;一个服务器端程序,一个客户端程序。服务器端和客户端都需要打印出交互过程。
下图为运行结果示例
Server.java
package com.Transmission;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server implements Runnable {
private static final int Port = 4096;
private static final int TTL = 20;
private final Socket socket;
String fileName = "test.txt";
public Server(Socket socket) {
super();
this.socket = socket;
}
public static void server() {
try {
ServerSocket serverSocket = new ServerSocket(Port);
int i = 0;
do {
i ++ ;
Socket socket = serverSocket.accept();
System.out.println("服务器的线程1,启动,与客户端" + i + "连接成功");
new Thread(new Server(socket)).start();
} while (i <= TTL);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
OutputStream outputStream = null;
FileInputStream fileInputStream = null;
try {
outputStream = socket.getOutputStream();
System.out.println("要传输的文件为: " + fileName);
outputStream.write(fileName.getBytes());
System.out.println("开始传输文件");
fileInputStream = new FileInputStream(fileName);
int data;
while (-1 != (data = fileInputStream.read())) {
outputStream.write(data);
}
System.out.println("文件传输结束");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileInputStream != null)
fileInputStream.close();
if (outputStream != null)
outputStream.close();
this.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Server.server();
}
}
Client.java
package com.Transmission;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
public class Client {
private static final String SERVERIP = "localhost";
private static final int Port = 4096;
private static final int clientPort = 8192;
public static void main(String[] args) {
byte[] buffer = new byte[2048];
Socket socket = new Socket();
try {
socket.connect(new InetSocketAddress(SERVERIP, Port), clientPort);
System.out.println("与服务器连接成功");
InputStream inputStream = socket.getInputStream();
int read = inputStream.read(buffer);
String fileName = new String(buffer, 0, read);
String newName = "test1.txt";
FileOutputStream fileOutputStream = new FileOutputStream(newName);
int data;
while ((data = inputStream.read()) != -1) {
fileOutputStream.write(data);
}
System.out.println("接收到的文件为:" + fileName);
System.out.println("保存为为:" + newName);
inputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
客户端:
服务器端:
现在文件结构如下:
$ tree .
.
├── Network.iml
├── out
│ └── production
│ └── Network
│ └── com
│ ├── Transmission
│ │ ├── Client.class
│ │ └── Server.class
│ ├── chattingroom
│ │ ├── PID.class
│ │ ├── Run.class
│ │ └── chat.class
│ ├── csmode
│ │ ├── Client.class
│ │ └── Server.class
│ └── ipaddress
│ ├── CSDNAddress.class
│ ├── IPAddress.class
│ └── SZUurl.class
├── src
│ └── com
│ ├── Transmission
│ │ ├── Client.java
│ │ └── Server.java
│ ├── chattingroom
│ │ ├── PID.java
│ │ ├── Run.java
│ │ └── chat.java
│ ├── csmode
│ │ ├── Client.java
│ │ └── Server.java
│ └── ipaddress
│ ├── CSDNAddress.java
│ ├── IPAddress.java
│ └── SZUurl.java
├── szu.html
├── test.txt
└── test1.txt
14 directories, 24 files