15.1 IP地址
实例270 获取计算机名与IP地址
import java.net.InetAddress;
public class NetDemo_1 {
public static void main(String[] args) {
try {
InetAddress ind = InetAddress.getLocalHost();
System.out.println(ind);
} catch (Exception e) {
System.out.println("没有找到主机的地址!");
}
}
}
实例271 获取网址的IP地址
import java.net.InetAddress;
import java.net.UnknownHostException;
public class NetDemo_2 {
public static void main(String[] args) {
try {
InetAddress ind = InetAddress.getByName("192.108.33.32");
System.out.println(ind.getHostName());
InetAddress ind1 = InetAddress.getByName("www.sina.com");
System.out.println(ind1);
} catch (UnknownHostException e) {
System.out.println(e);
}
}
}
实例272 判断两个网址的主机名是否一样
import java.net.InetAddress;
import java.net.UnknownHostException;
public class NetDemo_3 {
public static void main(String[] args) {
try {
// 创建两个InetAddress的对象
InetAddress ind = InetAddress.getByName("www.sohu.com");
InetAddress ind1 = InetAddress.getByName("sohu.com");
if (ind.equals(ind1)) {// 判断两个网址是否一样
System.out.println("这两个网址所显示的主机名一样!");
} else {
System.out.println("这两个网址所显示的主机名不一样。"); // 输出两个网址的主机名不一样
}
} catch (UnknownHostException e) {
// 没有查找到网址对应的主机
e.printStackTrace();
}
}
}
实例273 测试IP的类型
import java.net.InetAddress;
import java.net.UnknownHostException;
public class NetDemo_4 {
public static int getVersion(InetAddress ia) { //定义一个整型的静态方法
byte[] b = ia.getAddress(); //定义一个字节型的数组,并初始化。
if (b.length == 4) { //判断这个数组的长度是否等于4
return 4; //返回数值4
} else if (b.length == 16) {
return 6;
} else {
return -1;
}
}
public static char getClass(InetAddress ia) { //定义一个字符型的静态方法
byte[] b = ia.getAddress(); //定义一个字节型的数组,并初始化。
if (b.length != 4) { //判断这个 字符数组的长度是否不等于4
throw new IllegalArgumentException("no ipv6 address");//抛出一个非法参数异常
}
int firstByte = b[0]; //定义一个整型的变量
//使用多个if-else语句判断这个整型的变量与十六进制码比较
if ((firstByte & 0x80) == 0) {
return 'A';
} else if ((firstByte & 0xc0) == 0x80) {
return 'B';
} else if ((firstByte & 0xe0) == 0xc0) {
return 'C';
} else if ((firstByte & 0xF0) == 0xE0) {
return 'D';
} else if ((firstByte & 0xF8) == 0xF0) {
return 'E';
} else {
return 'F';
}
}
public static void main(String[] args) {
InetAddress ia = null;
try {
ia = InetAddress.getByName("www.sina.com");//给定一个网络域名
} catch (UnknownHostException e) {
e.printStackTrace();
}
int len;
char king;
len = getVersion(ia); //调用方法求出地址的长度
System.out.println("地址长度为:" + len);
king = getClass(ia); //调用方法求出地址的类型
System.out.println("地址的类型为:" + king);
}
}
实例274 查找主机
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class NetDemo_5 {
private static String lookup(String host) {
InetAddress ia;
byte[] b = null; // 初始化一个byte类型的数组
try {
ia = InetAddress.getByName(host);
} catch (UnknownHostException e) {
return "没有找到主机!";
}
if (isHostName(host)) { //判断是否有主机
String s = ""; //定义一个字符串
for (int i = 0; i < b.length; i++) { //循环遍历出主机的字符串
int c = b[i] < 0 ? (b[i] + 256) : b[i];
s += c;
if (i != b.length - 1) {
s += ",";
}
}
return s; //返回一个字符串
} else {
return ia.getHostName(); //返回一个字符串的
}
}
private static boolean isHostName(String host) { //创建一个静态的方法
char[] ch = host.toCharArray(); //定义一个字符数组,并初始化
for (int i = 0; i < ch.length; i++) {
if (!Character.isDigit(ch[i])) {
if (ch[i] != '.') {
return true;
}
}
}
return false;
}
public static void main(String[] args) {
if (args.length > 0) {
for (int i = 0; i < args.length; i++) { // 使用命令行
System.out.println(lookup(args[i]));
}
} else {
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
System.out.println();
while (true) {
try {
String s = br.readLine();
if (s.equals("exit")) { //判断如果字符串与“exit”相同,就结束当前的语句块
break;
}
System.out.println(lookup(s));
} catch (IOException e) {
System.err.println(e);
}
}
}
}
}
实例275 主机所支持的协议
15.2 URL类的使用
实例276 使用URL访问网页
import java.applet.Applet;
import java.awt.GridLayout;
import java.awt.Label;
import java.net.MalformedURLException;
import java.net.URL;
public class NetDemo_7 extends Applet{
public void init(){
URL url = this.getDocumentBase();
try {
URL url1 = new URL(url,"a.html"); //实例化一个URL对象
this.setLayout(new GridLayout(2,1));//设置布局
//添加标签
this.add(new Label(url.toString()));
this.add(new Label(url1.toString()));
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
实例277 URL的组成部分
import java.net.MalformedURLException;
import java.net.URL;
public class NetDemo_8 {
public static void main(String[] args){
for(int i=0;i<args.length;i++){
try {
URL url = new URL(args[i]);
System.out.println("URL的地址是:"+url);
System.out.println("URL的协议是:"+url.getProtocol());
System.out.println("用户信息是:"+url.getUserInfo());
String s = url.getHost();
if(s!=null){
int it = s.indexOf('@');
if(it!=-1){
s= s.substring(it+1);
System.out.println(s);
}
}else{
System.out.println(args[i]+"域名为空!");
}
System.out.println("端口是:"+url.getPort());
System.out.println("路径是:"+url.getPath());
System.out.println("文件类型是:"+url.getFile());
System.out.println("主机名是:"+url.getHost());
} catch (MalformedURLException e) {
System.out.println("不是一个URL地址!");
}
}
}
}
实例278 通过指定的URL可以获取网页的源代码
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
public class NetDemo_9 {
public static void main(String[] args) throws IOException{
if(args.length>0){
URL url;
try {
url = new URL(args[0]);
InputStream in = url.openStream();
in= new BufferedInputStream(in);
Reader r = new InputStreamReader(in);
int b;
while((b = r.read())!=-1){
System.out.print((char)b);
}
Object o = url.getContent();
System.out.println(o.getClass().getName());
} catch (MalformedURLException e) {
e.printStackTrace();
}catch (Exception e) {
System.out.print(e);
}
}
}
}
实例279 一对多通信模式
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class MySocketServer { // 操作Socket服务器端的类
public static void main(String[] args) { // java程序主入口处
try {
new StartServer(8080); // 传入端口实例化对象
} catch (Exception e) { // 捕获异常
System.out.println("服务器端进行监听出现异常:" + e.getMessage());
}
}
}
class StartServer extends ServerSocket { // socket面服务器端
private int port; // 端口
public StartServer(int port) throws IOException {
super(port); // 继承其类的port
this.port = port;
System.out.println("服务器启动成功,监听端口号为:" + port);
System.out.println("正在等待客户连接.........");
try {
while (true) { // 循环挂起等待客户的请求
Socket socketCon = accept();
new RunServer(socketCon, port); // 建立服务线程
}
} catch (IOException e) {
System.out.println("没有监听到客户端的信息......");
} finally {
close(); // 关闭通信资源
}
}
}
class RunServer extends Thread { // 继承线程类实现服务线程
private int port; // 端口
private Socket socketCon;
private BufferedReader in;
private PrintWriter out;
public RunServer(Socket s, int port) throws IOException {
this.port = port;
this.socketCon = s;
in = new BufferedReader(new InputStreamReader(socketCon
.getInputStream(), "gb2312")); // 读取客户端的数据流
// 获取写往客户端的数据输出流,true:自动刷新
out = new PrintWriter(socketCon.getOutputStream(), true);
out.println("服务器端连接成功........."); // 向客户发送连接信息
out.println("输入quit断开与服务器的连接");
start(); // 启动线程
}
public String infoUpperCase(String line) { // 处理信息
return line.toUpperCase(); // 将字符串大写
}
public void run() {
try {
boolean done = false;
while (!done) {
String line = in.readLine(); // 读取客户端每行的内容
if (line == null)
done = true;
else { // 显示客户端发送的内容
System.out.println("来自客户端的消息:" + line);
String message = infoUpperCase(line); // 信息处理
// 向客户端发送信息
out.println("来自服务器端的消息:" + message);
if (line.trim().equals("quit")) // 退出判断
done = true;
}
}
System.out.println("客户端终止发送信息......");
socketCon.close(); // 关闭通信资源
} catch (Exception e) { // 捕获异常
System.out.println("启动服务器端出现错误:" + e.getMessage());
}
}
}
/**--------文件名:MyOneClient.java-------------*/
class MyOneClient { // 操作Socket客户端类
public static void main(String[] args) { // java程序主入口处
try {
new Client1("localhost", 8080); // IP地址为本机,端口为8080
} catch (Exception e) { // 捕获异常
System.out.println("测试客户端连接出错:" + e.getMessage());
}
}
}
class PointClient { // Socket点客户端
private String host; // IP地址(域名)
private int port; // 端口号
public PointClient(String host, int port) { // 带参数构造方法进行初始化
this.host = host;
this.port = port;
connectServer(); // 调用连接方法
}
public void connectServer() { // 连接方法
try {
Socket socketConn; // 声明Socket连接
// 判断IP地址(域名)如果是本机localhost
if (host.equals("localhost") || host.equals("127.0.0.1")) {
// 创建本地连接
socketConn = new Socket(InetAddress.getLocalHost(), port);
} else { // 创建远程连接
socketConn = new Socket(InetAddress.getByName(host), port);
}
BufferedReader stdin = new BufferedReader(new InputStreamReader(
System.in)); // 获得从键盘输入的流
PrintWriter out = new PrintWriter(socketConn.getOutputStream(),
true); // 获得服务器写内容的数据流
BufferedReader in = new BufferedReader(new InputStreamReader(
socketConn.getInputStream())); // 获得接收服务器发送内容的缓冲流
System.out.println("服务器信息:" + in.readLine()); // 从服务器获得信息
System.out.println("服务器信息:" + in.readLine());
System.out.print("请输入>"); // 用户输入
boolean done = false;
while (!done) {
String line = stdin.readLine(); // 获得从键盘输入的每行字符
out.println(line); // 发送到服务端
if (line.equalsIgnoreCase("quit")) // 读到quit则结束循环
done = true;
String info = in.readLine(); // 从服务器读取字符串
System.out.println("服务器信息:" + info); // 显示从服务器发送来的数据
if (!done) // 用户输入
System.out.print("请输入>");
}
socketConn.close(); // 关闭资源
} catch (SecurityException e) { // 捕获安全性错误时引发的异常
System.out.println("连接服务器出现安全问题!");
} catch (IOException e) { // 捕获IO流异常
System.out.println("连接服务器出现I/O错误!");
}
}
}
/**--------文件名:MyTwoClient.java-------------*/
class MyTwoClient { // 操作Socket客户端类
public static void main(String[] args) { // java程序主入口处
try {
new Client1("localhost", 8080); // IP地址为本机,端口为80
} catch (Exception e) { // 捕获异常
System.out.println("测试客户端连接出错:" + e.getMessage());
}
}
}
class Client1 { // Socket客户端
private String host; // IP地址(域名)
private int port; // 端口号
public Client1(String host, int port) { // 带参数构造方法进行初始化
this.host = host;
this.port = port;
connectServer(); // 调用连接方法
}
public void connectServer() { // 连接方法
try {
Socket socketConn; // 声明Socket连接
// 判断IP地址(域名)如果是本机localhost
if (host.equals("localhost") || host.equals("127.0.0.1")) {
// 创建本地连接
socketConn = new Socket(InetAddress.getLocalHost(), port);
} else { // 创建远程连接
socketConn = new Socket(InetAddress.getByName(host), port);
}
BufferedReader stdin = new BufferedReader(new InputStreamReader(
System.in)); // 获得从键盘输入的流
PrintWriter out = new PrintWriter(socketConn.getOutputStream(),
true); // 获得服务器写内容的数据流
BufferedReader in = new BufferedReader(new InputStreamReader(
socketConn.getInputStream())); // 获得接收服务器发送内容的缓冲流
System.out.println("服务器信息:" + in.readLine()); // 从服务器获得信息
System.out.println("服务器信息:" + in.readLine());
System.out.print("请输入>"); // 用户输入
boolean done = false;
while (!done) {
String line = stdin.readLine(); // 获得从键盘输入的每行字符
out.println(line); // 发送到服务端
if (line.equalsIgnoreCase("quit")) // 读到quit则结束循环
done = true;
String info = in.readLine(); // 从服务器读取字符串
System.out.println("服务器信息:" + info); // 显示从服务器发送来的数据
if (!done) // 用户输入
System.out.print("请输入>");
}
socketConn.close(); // 关闭资源
} catch (SecurityException e) { // 捕获安全性错误时引发的异常
System.out.println("连接服务器出现安全问题!");
} catch (IOException e) { // 捕获IO流异常
System.out.println("连接服务器出现I/O错误!");
}
}
}
实例280 自制浏览器
import java.awt.event.WindowEvent;
import java.io.IOException;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
//实现一个浏览器
class LinkFollower implements HyperlinkListener{
private JEditorPane jep;
public LinkFollower(JEditorPane jep){
this.jep= jep;
}
public void hyperlinkUpdate(HyperlinkEvent he){
if(he.getEventType()==HyperlinkEvent.EventType.ACTIVATED){
try {
jep.setPage(he.getURL());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class NetDemo_15{
public static void main(String[] args){
String initPage = "http://www.sina.com";
if(args.length>0){
initPage = args[0];
JEditorPane jep = new JEditorPane();
jep.setEditable(false);
jep.addHyperlinkListener(new LinkFollower(jep));
try {
jep.setPage(initPage);
} catch (IOException e) {
e.printStackTrace();
}
JScrollPane jsp = new JScrollPane(jep);
JFrame jf = new JFrame("简单浏览器");
jf.setDefaultCloseOperation(WindowEvent.COMPONENT_SHOWN);
jf.getContentPane().add(jsp);
jf.setSize(512,324);
jf.show();
}
}
}
实例281 扫描TCP端口
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class NetDemo_16 {
public static void main(String[] args){
String str = "localhost";
if(args.length>0){
str = args[0];
}
for(int i=100;i<500;i++){ //使用循环扫描端口
try {
Socket s = new Socket();
System.out.println("There is a server on"+i+"of"+s);
} catch (Exception e) {
e.printStackTrace();
break;
}
}
}
}
实例282 TCP协议服务器
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPSocketServer {
public static void main(String[] args) { // java程序主入口处
try {
Server server = new Server(8080); // 传入端口号实例化对象
} catch (Exception e) { // 捕获异常
System.out.println("测试服务器端监听出错:" + e.getMessage());
}
}
}
class Server { // Socket服务器端
private int port; // 端口
public Server(int port) { // 带参数的构造方法进行初始化
this.port = port;
start(); // 调用启动服务器端的方法
}
public String infoUpperCase(String line) { // 处理信息
return line.toUpperCase(); // 将字符串大写
}
public void start() { // 启动服务器端
try {
// 根据端口创建服务器端Socket对象
ServerSocket serverSocket = new ServerSocket(port);
// 显示连接信息
System.out.println("服务器已启动,监听端口号为:" + port);
System.out.println("正在等待客户端连接.........");
// 挂起等待客户的请求
Socket socketAccept = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(
socketAccept.getInputStream())); // 获取读取客户端的数据流
// 获取写往客户端的数据输出流,true:自动刷新
PrintWriter out = new PrintWriter(socketAccept.getOutputStream(),
true);
out.println("服务器端连接成功........."); // 向客户发送连接信息
out.println("输入quit断开与服务器的连接");
boolean done = false;
while (!done) {
String line = in.readLine(); // 读取客户端每行的内容
if (line == null) { // 没有写则不读取
done = true;
} else {
// 显示客户端发送的内容
System.out.println("来自客户端的信息:" + line);
// 信息处理
String message = infoUpperCase(line);
// 向客户端发送信息
out.println("来自服务器端的信息:" + message);
if (line.trim().equals("quit")) // 退出判断
done = true;
}
}
socketAccept.close(); // 关闭通信资源
} catch (Exception e) { // 捕获异常
System.out.println("启动服务器端出现错误:" + e.getMessage());
}
}
}
实例283 TCP协议客户机
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class TCPSocketClient {
public static void main(String[] args) { // java程序主入口处
try {
new Client("localhost", 8080); // IP地址为本机,端口为80
} catch (Exception e) { // 捕获异常
System.out.println("测试客户端连接出错:" + e.getMessage());
}
}
}
class Client { // Socket客户端
private String host; // IP地址(域名)
private int port; // 端口号
public Client(String host, int port) { // 带参数构造方法进行初始化
this.host = host;
this.port = port;
connectServer(); // 调用连接方法
}
public void connectServer() { // 连接方法
try {
Socket socketConn; // 声明Socket连接
// 判断IP地址(域名)如果是本机localhost
if (host.equals("localhost") || host.equals("127.0.0.1")) {
// 创建本地Socket连接
socketConn = new Socket(InetAddress.getLocalHost(), port);
} else { // 创建远程Socket连接
socketConn = new Socket(InetAddress.getByName(host), port);
}
BufferedReader stdin = new BufferedReader(new InputStreamReader(
System.in)); // 获得从键盘输入的流
PrintWriter out = new PrintWriter(socketConn.getOutputStream(),
true); // 获得服务器写内容的数据流
BufferedReader in = new BufferedReader(new InputStreamReader(
socketConn.getInputStream()));// 获得接收服务器发送内容的缓冲流
// 从服务器获得信息
System.out.println("服务器信息:" + in.readLine());
System.out.println("服务器信息:" + in.readLine());
System.out.print("请输入>"); // 用户输入
boolean done = false;
while (!done) {
String line = stdin.readLine(); // 获得从键盘输入的每行字符
out.println(line); // 发送到服务端
if (line.equalsIgnoreCase("quit")) // 读到quit则结束循环
done = true;
String info = in.readLine(); // 从服务器读取字符串
System.out.println("服务器信息:" + info); // 显示从服务器发送来的数据
if (!done) // 用户输入
System.out.print("请输入>");
}
socketConn.close(); // 关闭资源
} catch (SecurityException e) { // 捕获安全性错误时引发的异常
System.out.println("连接服务器出现安全问题!");
} catch (IOException e) { // 捕获IO流异常
System.out.println("连接服务器出现I/O错误!");
}
}
}
实例284 Socket连接信息
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class NetDemo_17 {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
try {
Socket s = new Socket(args[i], 80);
System.out.println("Connected to" + s.getInetAddress()
+ "on port" + s.getPort() + "from port"
+ s.getLocalPort() + "of" + s.getLocalAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
实例285 Echo服务的客户端是如何实现的?
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class EchoClient {
public static void main(String args[]) {
try {
Socket connection = new Socket("", 7);// 创建Socket对象,Echo协议对应的端口为7号 System.out.println("已建立连接:");
DataInputStream in = new DataInputStream(connection
.getInputStream());// 根据返回的Socket对象的输入流创建数据输入流
DataOutputStream out = new DataOutputStream(connection
.getOutputStream());// 根据返回的Socket对象的输出流创建数据输出流
String line = new String("");
while (!line.toUpperCase().equals(".QUIT")) {
System.out.println("输入字符串: ");
line = EchoClient.readString();// 由键盘输入字符串
System.out.println("\t字符串发送到服务器 ...");
out.writeUTF(line);// 以UTF的编码形式将一个字符串写入数据输出流
System.out.println("\t等待服务器响应 ...");
line = in.readUTF();// 以UTF的编码形式从数据输入流中读字符串
System.out.println("Received: " + line);// 将读取的字符串显示出来
}
in.close();
out.close();
connection.close();
} catch (UnknownHostException e) {
System.err.println("Unknown host: " + args[0]);
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
public static String readString() {
String string = new String();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));// 创建一个可键盘录入的字符串缓冲区
try {
string = in.readLine();
} catch (IOException e) {
}
return string;
}
}
实例286 检测本机的服务端口
import java.io.IOException;
import java.net.ServerSocket;
public class usrLocalPostScanner {
public static void main(String[] args) {
// 循环访问端口
for (int port = 1; port <= 65535; port++) {
try {
// 建立新的服务端口
// 如果在此端口已经有服务存在,则抛出异常
ServerSocket server = new ServerSocket(port);
} catch (IOException e) {
// 打印出异常
System.out.println("There is a server on port " + port + ".");
}
}
}
}
实例287 下载的页面不丢失链接
import java.net.URLEncoder;
//下载的页面不丢失链接
public class NetDemo_11 {
public static void main(String[] args){
System.out.println(URLEncoder.encode("This string has spaces"));
System.out.println(URLEncoder.encode("This*string*has*asterisks"));
System.out.println(URLEncoder.encode("This%string%has%persent%signs"));
System.out.println(URLEncoder.encode("This+string+has+pulses"));
System.out.println(URLEncoder.encode("This/string/has/slashes"));
System.out.println(URLEncoder.encode("This:string:has:colors"));
System.out.println(URLEncoder.encode("This-string-has-tildes"));
System.out.println(URLEncoder.encode("This(string)has(parentheses)"));
System.out.println(URLEncoder.encode("This.string.has.periods"));
System.out.println(URLEncoder.encode("This&string&has&ersands"));
}
}
实例288 如何对网页进行重新定向
import java.applet.Applet;
import java.net.MalformedURLException;
import java.net.URL;
//如何对网页进行重新定向
public class NetDemo_12 extends Applet{
public void init(){
try {
getAppletContext().showDocument(new URL("http://delfault.myetang.com"),"_blank");
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
实例289 在Internet上搜索对象
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
//在Intenet上搜索对象
public class NetDemo_13 {
public static void main(String[] args) throws IOException{
String target = "";
for(int i=0;i<args.length;i++){
target +=args[i]+"";
}
target= target.trim();
URL url;
try {
url = new URL("http://www.baidu.com/");
InputStream in = new BufferedInputStream(url.openStream());
InputStreamReader isr = new InputStreamReader(in);
int b;
while((b= isr.read())!=-1){
System.out.print((char)(b));
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
实例290 LAN使用代理服务器
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.net.ServerSocket;
import java.net.Socket;
public class LANProxy extends Thread { // 操作实现代理服务器的类
protected Socket socket; // 传入数据用的Socket
private static String parent = null; // 上级代理服务器
private static int parentPort = -1;
public static int RETRIES = 5; // 在放弃之前尝试连接远程主机的次数
public static int PAUSE = 5; // 在两次连接尝试之间的暂停时间
public static int TIMEOUT = 50; // 等待Socket输入的等待时间
public static int BUFSIZ = 1024; // 输入的缓冲大小
public static boolean logging = false; // 是否要求代理服务器在日志中记录所有已传输的数据
public static OutputStream log = null; // 默认日志例程将向该OutputStream对象输出日志信息
public void run() { // 执行操作的线程
String line;
String host;
int port = 80;
Socket outbound = null;
try {
socket.setSoTimeout(TIMEOUT); // 设置超时时间
InputStream is = socket.getInputStream(); // 创建输入流
OutputStream os = null;
try {
line = ""; // 获取请求行的内容
host = "";
int state = 0;
boolean space;
while (true) { // 无限循环
int c = is.read(); // 读取输入流的信息
if (c == -1) // 没有读取信息
break;
if (logging)
proxyLog(c, true); // 将信息写入日志
space = Character.isWhitespace((char) c);// 判断是否为空白字符
switch (state) { // 判断状态
case 0:
if (space)
continue; // 跳过本次循环
state = 1; // 更改状态
case 1:
if (space) {
state = 2;
continue; // 跳过本次循环
}
line = line + (char) c; // 添加读取的信息
break;
case 2:
if (space)
continue; // 跳过空白字符
state = 3; // 更改状态
case 3:
if (space) { // 如果是空白字符
state = 4; // 更改状态
String host0 = host; // 取出网址
int n;
n = host.indexOf("//"); // 获取网址(不包括协议)
if (n != -1) // 没有找到
host = host.substring(n + 2);
n = host.indexOf('/');
if (n != -1) // 没有找到/
host = host.substring(0, n);
n = host.indexOf(":"); // 分析可能存在的端口号
if (n != -1) { // 没有找到:
port = Integer.parseInt(host.substring(n + 1));
host = host.substring(0, n);
}
host = outLog(host0, host, port, socket);// 获得网站域名
if (parent != null) {
host = parent;
port = parentPort;
}
int retry = RETRIES;
while (retry-- != 0) {
try { // 创建连接对象
outbound = new Socket(host, port);
break;
} catch (Exception e) {
System.out.println("无法创建连接:"
+ e.getMessage());
}
Thread.sleep(PAUSE); // 设置线程等待
}
if (outbound == null)
break;
outbound.setSoTimeout(TIMEOUT); // 设置超时时间
os = outbound.getOutputStream(); // 获得输出流对象
os.write(line.getBytes()); // 将信息写入流
os.write(' ');
os.write(host0.getBytes()); // 将信息写入流
os.write(' ');
outInfo(is, outbound.getInputStream(), os, socket
.getOutputStream()); // 调用方法将信息写入日志
break;
}
host = host + (char) c;
break;
}
}
} catch (IOException e) {
}
} catch (Exception e) {
} finally {
try {
socket.close(); // 释放资源
} catch (Exception e1) {
}
try {
outbound.close();
} catch (Exception e2) {
}
}
}
void outInfo(InputStream is0, InputStream is1, OutputStream os0,
OutputStream os1) throws IOException { // 读取流中信息写入日志
try {
int ir;
byte bytes[] = new byte[BUFSIZ]; // 创建字节数组,大小:1024
while (true) {
try {
if ((ir = is0.read(bytes)) > 0) { // 判断读取输入流的信息
os0.write(bytes, 0, ir); // 读取数据写入输出流对象中
if (logging)
proxyLog(bytes, 0, ir, true); // 写入日志
} else if (ir < 0) // 读取完毕
break;
} catch (InterruptedIOException e) { // 捕获中断IO流异常
}
try {
if ((ir = is1.read(bytes)) > 0) { // 判断读取输入流的信息
os1.write(bytes, 0, ir); // 读取数据写入输出流对象中
if (logging)
proxyLog(bytes, 0, ir, false); // 写入日志
} else if (ir < 0) // 读取完毕
break;
} catch (InterruptedIOException e) { // 捕获中断IO流异常
}
}
} catch (Exception e0) { // 捕获异常
}
}
// 用来把一个代理服务器链接到另一个代理服务器(需要指定另一个服务器的名称和端口)。
public static void setProxy(String name, int port) {
parent = name;
parentPort = port;
}
public LANProxy(Socket s) { // 创建一个代理线程
socket = s;
start(); // 启动线程
}
public void proxyLog(int c, boolean browser) throws IOException { // 写日志
log.write(c);
}
public void proxyLog(byte[] bytes, int offset, int len, boolean browser)
throws IOException { // 循环写日志
for (int i = 0; i < len; i++)
proxyLog((int) bytes[offset + i], browser);
}
// 默认情况下,日志信息输出到控制台或文件
public String outLog(String url, String host, int port, Socket sock) {
java.text.DateFormat cal = java.text.DateFormat.getDateTimeInstance();
System.out.println(cal.format(new java.util.Date()) + " - " + url + " "
+ sock.getInetAddress() + "\n");
return host;
}
public static void startProxy(int port, Class clobj) {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(port); // 根据端口创建服务器端Socket对象
while (true) {
Class[] objClass = new Class[1]; // 创建类数组,大小为1
Object[] obj = new Object[1]; // 创建对象数组,大小为1
objClass[0] = Socket.class; // 添加Socket类
try { // 创建代理服务器实例
Constructor cons = clobj.getDeclaredConstructor(objClass);
obj[0] = serverSocket.accept(); // 挂起等待客户的请求
cons.newInstance(obj); // 创建HttpProxy或其派生类的实例
} catch (Exception e) {
Socket socket = (Socket) obj[0];// 对象强制转换
try {
socket.close(); // 释放资源
} catch (Exception ec) {
}
}
}
} catch (IOException e) {
}
}
public static void main(String args[]) { // java程序主入口处
System.out.println("LAN使用代理服务器连接成功......");
LANProxy.log = System.out; // 日志信息输出到控制台
LANProxy.logging = false;
LANProxy.startProxy(8080, LANProxy.class);// 调用方法
}
}
实例291 BBS论坛服务器端
package net;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.*;
import javax.swing.border.TitledBorder;
/**
* 聊天室的服务器端程序,GUI界面
*/
public class BBSServer extends JFrame {
static JLabel statusBar = new JLabel(); // 状态栏标签
// 显示客户端的连接信息的列表
static java.awt.List connectInfoList = new java.awt.List(10);
// 保存当前处理客户端请求的处理器线程
static Vector clientProcessors = new Vector(10);
// 当前的连接数
static int activeConnects = 0;
// 构造方法
public BBSServer() {
init();
try {
// 设置界面为系统默认外观
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.updateComponentTreeUI(this);
} catch (Exception e) {
e.printStackTrace();
}
}
private void init() {
this.setTitle("BBS论坛1号聊天室");
statusBar.setText("");
// 初始化菜单
JMenu fileMenu = new JMenu();
fileMenu.setText("文件");
JMenuItem exitMenuItem = new JMenuItem();
exitMenuItem.setText("退出");
exitMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
exitActionPerformed(e);
}
});
fileMenu.add(exitMenuItem);
JMenuBar menuBar = new JMenuBar();
menuBar.add(fileMenu);
this.setJMenuBar(menuBar);
// 将组件进行布局
JPanel jPanel1 = new JPanel();
jPanel1.setLayout(new BorderLayout());
JScrollPane pane = new JScrollPane(connectInfoList);
pane.setBorder(new TitledBorder(BorderFactory.createEtchedBorder(
Color.red, new Color(134, 134, 0)), "客户端IP一览表"));
jPanel1.add(new JScrollPane(pane), BorderLayout.CENTER);
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(statusBar, BorderLayout.SOUTH);
this.getContentPane().add(jPanel1, BorderLayout.CENTER);
this.pack();
}
/** 退出菜单项事件 */
public void exitActionPerformed(ActionEvent e) {
// 向客户端发送断开连接信息
sendMsgToClients(new StringBuffer(Message.QUIT_IDENTIFER));
closeAll(); // 关闭所有的连接
System.exit(0);
}
/** 处理窗口关闭事件 */
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
exitActionPerformed(null);
}
}
/** 刷新聊天室,不断刷新clientProcessors,制造最新的用户列表 */
public static void RefreshRoom() {
StringBuffer people = new StringBuffer(Message.PEOPLE_IDENTIFER);
for (int i = 0; i < clientProcessors.size(); i++) {
MessFromClient c = (MessFromClient) clientProcessors.elementAt(i);
people.append(Message.SEPERATOR).append(c.clientName);
}
// 用sendClients方法向客户端发送用户列表的信息
sendMsgToClients(people);
}
/** 向所有客户端群发消息 */
public static synchronized void sendMsgToClients(StringBuffer msg) {
for (int i = 0; i < clientProcessors.size(); i++) {
MessFromClient c = (MessFromClient) clientProcessors.elementAt(i);
System.out.println("send msg: " + msg);
c.send(msg);
}
}
/** 关闭所有连接 */
public static void closeAll() {
while (clientProcessors.size() > 0) {
MessFromClient c = (MessFromClient) clientProcessors.firstElement();
try {
// 关闭socket连接和处理线程
c.socket.close();
c.toStop();
} catch (IOException e) {
System.out.println("Error:" + e);
} finally {
clientProcessors.removeElement(c);
}
}
}
/**
* 判断客户端是否合法。 不允许同一客户端重复登陆,所谓同一客户端是指IP和名字都相同。
*/
public static boolean isCheck(MessFromClient newclient) {
if (clientProcessors.contains(newclient)) {
return false;
} else {
return true;
}
}
/**
* 断开某个连接,并且从连接列表中删除
*/
public static void disconnect(MessFromClient client) {
disconnect(client, true);
}
/**
* 断开某个连接,根据要求决定是否从连接列表中删除
*/
public static synchronized void disconnect(MessFromClient client,
boolean toRemoveFromList) {
try {
// 在服务器端程序的list框中显示断开信息
connectInfoList.add(client.clientIP + "断开连接");
BBSServer.activeConnects--; // 将连接数减1
String constr = "当前在线人数:" + BBSServer.activeConnects + "人";
statusBar.setText(constr);
// 向客户发送断开连接信息
client.send(new StringBuffer(Message.QUIT_IDENTIFER));
client.socket.close();
} catch (IOException e) {
System.out.println("Error:" + e);
} finally {
// 从clients数组中删除此客户的相关socket等信息, 并停止线程。
if (toRemoveFromList) {
clientProcessors.removeElement(client);
client.toStop();
}
}
}
public static void main(String[] args) {
BBSServer chatServer1 = new BBSServer();
chatServer1.setVisible(true);
System.out.println("Server starting ...");
ServerSocket server = null;
try {
// 服务器端开始侦听
server = new ServerSocket(Message.SERVER_PORT);
} catch (IOException e) {
System.out.println("Error:" + e);
System.exit(1);
}
while (true) {
// 如果当前客户端数小于MAX_CLIENT个时接受连接请求
if (clientProcessors.size() < Message.MAX_CLIENT) {
Socket socket = null;
try {
// 收到客户端的请求
socket = server.accept();
if (socket != null) {
System.out.println(socket + "连接");
}
} catch (IOException e) {
System.out.println("Error:" + e);
}
// 定义并实例化一个ClientProcessor线程类,用于处理客户端的消息
MessFromClient c = new MessFromClient(socket);
if (isCheck(c)) {
clientProcessors.addElement(c); // 添加到列表
int connum = ++BBSServer.activeConnects; // 如果客户端合法,则继续
// 在状态栏里显示连接数
String constr = "当前在线人数:" + connum + "人";
BBSServer.statusBar.setText(constr);
// 将客户socket信息写入list框
BBSServer.connectInfoList.add(c.clientIP + "连接");
c.start();
RefreshRoom(); // 通知所有客户端用户列表发生变化
} else {
// 如果客户端不合法
c.ps.println("不允许重复登陆");
disconnect(c, false);
}
} else {
// 如果客户端超过了MAX_CLIENT个,则等待一段时间再尝试接受请求
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
}
}
/**
* 处理客户端发送的请求的线程
*/
class MessFromClient extends Thread {
Socket socket; // 存储一个连接客户端的socket信息
String clientName; // 存储客户端的连接姓名
String clientIP; // 存储客户端的ip信息
BufferedReader br; // 用来实现接受从客户端发来的数据流
PrintStream ps; // 用来实现向客户端发送信息的打印流
boolean running = true;
/** 构造方法 */
public MessFromClient(Socket s) {
socket = s;
try {
// 初始化输入输出流
br = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
ps = new PrintStream(socket.getOutputStream());
// 读取收到的信息,第一条信息是客户端的名字、IP信息
String clientInfo = br.readLine();
// 读取信息,根据消息分隔符解析消息
StringTokenizer stinfo = new StringTokenizer(clientInfo,
Message.SEPERATOR);
String head = stinfo.nextToken();
if (head.equals(Message.CONNECT_IDENTIFER)) {
if (stinfo.hasMoreTokens()) {
// 关键字后的第二段数据是客户名信息
clientName = stinfo.nextToken();
}
if (stinfo.hasMoreTokens()) {
// 关键字后的第三段数据是客户ip信息
clientIP = stinfo.nextToken();
}
System.out.println(head); // 在控制台打印头信息
}
} catch (IOException e) {
System.out.println("Error:" + e);
}
}
/** 向客户端发送消息 */
public void send(StringBuffer msg) {
ps.println(msg);
ps.flush();
}
// 线程运行方法
public void run() {
while (running) {
String line = null;
try {
// 读取客户端发来的数据流
line = br.readLine();
} catch (IOException e) {
System.out.println("Error" + e);
BBSServer.disconnect(this);
BBSServer.RefreshRoom();
return;
}
// 客户已离开
if (line == null) {
BBSServer.disconnect(this);
BBSServer.RefreshRoom();
return;
}
StringTokenizer st = new StringTokenizer(line, Message.SEPERATOR);
String keyword = st.nextToken();
// 如果关键字是MSG则是客户端发来的聊天信息
if (keyword.equals(Message.MSG_IDENTIFER)) {
StringBuffer msg = new StringBuffer(Message.MSG_IDENTIFER)
.append(Message.SEPERATOR);
msg.append(clientName);
msg.append(st.nextToken("\0"));
// 再将某个客户发来的聊天信息发送到每个连接客户的聊天栏中
BBSServer.sendMsgToClients(msg);
} else if (keyword.equals(Message.QUIT_IDENTIFER)) {
// 如果关键字是QUIT则是客户端发来断开连接的信息
BBSServer.disconnect(this); // 服务器断开与这个客户的连接
// 继续监听聊天室并刷新其他客户的聊天人名list
BBSServer.RefreshRoom();
running = false;
}
}
}
public void toStop() {
running = false;
}
// 覆盖Object类的equals方法
public boolean equals(Object obj) {
if (obj instanceof MessFromClient) {
MessFromClient obj1 = (MessFromClient) obj;
if (obj1.clientIP.equals(this.clientIP)
&& (obj1.clientName.equals(this.clientName))) {
return true;
}
}
return false;
}
// 覆盖Object类的hashCode方法
public int hashCode() {
return (this.clientIP + Message.SEPERATOR + this.clientName).hashCode();
}
}
package net;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.StringTokenizer;
import javax.swing.*;
import javax.swing.border.TitledBorder;
/**
* 聊天室的客户端程序,GUI界面。
*/
public class BBSClient extends JFrame implements ActionListener {
// 登陆聊天室的名字标签和输入框
JLabel nameLabel = new JLabel();
JTextField nameTextField = new JTextField(15);
// 连接和断开连接的按钮
JButton connectButton = new JButton();
JButton disConnectButton = new JButton();
JTextArea chatContentTextArea = new JTextArea(9, 30); // 聊天室内容的文本域
JButton sendMsgButton = new JButton(); // 发送消息的按钮
JTextField msgTextField = new JTextField(20); // 消息输入框
JLabel msglabel = new JLabel();
java.awt.List peopleList = new java.awt.List(10); // 聊天室用户列表
/** 以下定义数据流和网络变量 */
Socket soc = null;
PrintStream ps = null;
// 客户端侦听服务器消息的线程
ListenClentThread listener = null;
public BBSClient() {
init();
}
// 初始化图形界面
public void init() {
this.setTitle("欢迎来到1号聊天室");
// 初始化按钮和标签
nameLabel.setText("姓名:");
connectButton.setText("登 录");
connectButton.addActionListener(this);
disConnectButton.setText("退 出");
disConnectButton.addActionListener(this);
// 设置聊天内容不可编辑
chatContentTextArea.setEditable(false);
sendMsgButton.setText("发送信息");
sendMsgButton.addActionListener(this);
msgTextField.setText("");
// panel1放置输入姓名和连接两个按钮
JPanel panel1 = new JPanel();
panel1.setLayout(new FlowLayout());
panel1.add(nameLabel);
panel1.add(nameTextField);
panel1.add(connectButton);
panel1.add(disConnectButton);
// 用于放置聊天信息显示和聊天人员列表
JPanel panel2 = new JPanel();
panel2.setLayout(new FlowLayout());
JScrollPane pane1 = new JScrollPane(chatContentTextArea);
pane1.setBorder(new TitledBorder(BorderFactory.createEtchedBorder(
Color.white, new Color(134, 134, 134)), "聊天内容"));
panel2.add(pane1);
JScrollPane pane2 = new JScrollPane(peopleList);
pane2.setBorder(new TitledBorder(BorderFactory.createEtchedBorder(
Color.white, new Color(134, 134, 134)), "在线用户"));
panel2.add(pane2);
// 用于放置发送信息区域
JPanel panel3 = new JPanel();
panel3.setLayout(new FlowLayout());
panel3.add(msglabel);
panel3.add(msgTextField);
panel3.add(sendMsgButton);
// 将组件添加到界面
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(panel1, BorderLayout.NORTH);
this.getContentPane().add(panel2, BorderLayout.CENTER);
this.getContentPane().add(panel3, BorderLayout.SOUTH);
this.pack();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.updateComponentTreeUI(this);
} catch (Exception e) {
e.printStackTrace();
}
}
/** 关闭聊天室客户端事件 */
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
// 如果是关闭聊天室客户端,则断开连接
disconnect();
dispose();
System.exit(0);
}
}
/** 处理按钮事件 */
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == connectButton) {
// 如果点击连接按钮
if (soc == null) {
try {
// 使用端口2525实例化一个本地套接字
soc = new Socket(InetAddress.getLocalHost(),
Message.SERVER_PORT);
System.out.println(soc); // 在控制台打印实例化的结果
ps = new PrintStream(soc.getOutputStream());// 将ps指向soc的输出流
// 定义一个字符缓冲存储发送信息
StringBuffer info = new StringBuffer(
Message.CONNECT_IDENTIFER)
.append(Message.SEPERATOR);
// 其中INFO为关键字让服务器识别为连接信息
// 并将name和ip用":"分开,在服务器端将用一个
// StringTokenizer类来读取数据
String userinfo = nameTextField.getText()
+ Message.SEPERATOR
+ InetAddress.getLocalHost().getHostAddress();
ps.println(info.append(userinfo));
ps.flush();
// 将客户端线程实例化,并启动
listener = new ListenClentThread(this, nameTextField
.getText(), soc);
listener.start();
} catch (IOException e) {
System.out.println("Error:" + e);
disconnect();
}
}
} else if (source == disConnectButton) {
// 如果点击断开连接按钮
disconnect();
} else if (source == sendMsgButton) {
// 如果点击发送按钮
if (soc != null) {
// 定义并实例化一个字符缓冲存储发送的聊天信息
StringBuffer msg = new StringBuffer(Message.MSG_IDENTIFER)
.append(Message.SEPERATOR);
// 用打印流发送聊天信息
ps.println(msg.append(msgTextField.getText()));
ps.flush();
}
}
}
/** 断开与服务器的连接 */
public void disconnect() {
if (soc != null) {
try {
// 用打印流发送QUIT信息通知服务器断开此次通信
ps.println(Message.QUIT_IDENTIFER);
ps.flush();
soc.close(); // 关闭套接字
listener.toStop();
soc = null;
} catch (IOException e) {
System.out.println("Error:" + e);
}
}
}
public static void main(String[] args) {
BBSClient client = new BBSClient();
client.setVisible(true);
}
/** 客户端线程类用来监听服务器传来的信息 */
class ListenClentThread extends Thread {
String name = null; // 存储客户端连接后的name信息
BufferedReader br = null; // 客户端接受服务器数据的输入流
PrintStream ps = null; // 实现从客户端发送数据到服务器的打印流
Socket socket = null; // 存储客户端的socket信息
BBSClient parent = null; // 存储当前运行的ChatClient实例
boolean running = true;
// 构造方法
public ListenClentThread(BBSClient p, String n, Socket s) {
// 接受参数
parent = p;
name = n;
socket = s;
try {
// 实例化两个数据流
br = new BufferedReader(new InputStreamReader(s
.getInputStream()));
ps = new PrintStream(s.getOutputStream());
} catch (IOException e) {
System.out.println("Error:" + e);
parent.disconnect();
}
}
// 停止侦听
public void toStop() {
this.running = false;
}
// 线程运行方法
public void run() {
String msg = null;
while (running) {
msg = null;
try {
// 读取从服务器传来的信息
msg = br.readLine();
System.out.println("receive msg: " + msg);
} catch (IOException e) {
System.out.println("Error:" + e);
parent.disconnect();
}
// 如果从服务器传来的信息为空则断开此次连接
if (msg == null) {
parent.listener = null;
parent.soc = null;
parent.peopleList.removeAll();
running = false;
return;
}
// 用StringTokenizer类来实现读取分段字符
StringTokenizer st = new StringTokenizer(msg, Message.SEPERATOR);
// 读取信息头即关键字用来识别是何种信息
String keyword = st.nextToken();
if (keyword.equals(Message.PEOPLE_IDENTIFER)) {
// 如果是PEOPLE则是服务器发来的客户连接信息
// 主要用来刷新客户端的用户列表
parent.peopleList.removeAll();
// 遍历st取得目前所连接的客户
while (st.hasMoreTokens()) {
String str = st.nextToken();
parent.peopleList.add(str);
}
} else if (keyword.equals(Message.MSG_IDENTIFER)) {
// 如果关键字是MSG则是服务器传来的聊天信息,
// 主要用来刷新客户端聊天信息区将每个客户的聊天内容显示出来
String usr = st.nextToken();
parent.chatContentTextArea.append(usr);
parent.chatContentTextArea.append(st.nextToken("\0"));
parent.chatContentTextArea.append("\r\n");
} else if (keyword.equals(Message.QUIT_IDENTIFER)) {
// 如果关键字是QUIT则是服务器关闭的信息, 切断此次连接
System.out.println("Quit");
try {
running = false;
parent.listener = null;
parent.soc.close();
parent.soc = null;
} catch (IOException e) {
System.out.println("Error:" + e);
} finally {
parent.soc = null;
parent.peopleList.removeAll();
}
break;
}
}
// 清除用户列表
parent.peopleList.removeAll();
}
}
}
实例292 UDP报文的发送与接收
import java.io.File;
import java.io.FileInputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**--------文件名:UDPServer.java-------------*/
public class UDPServer {
public static void main(String args[]) {
try {
System.out.println("UDP服务端启动成功,等待接收消息...");
if (args.length != 1) {
throw new IllegalArgumentException("参数个数有误");
}
int port = Integer.parseInt(args[0]); // 从命令行中获取端口号参数
// 创建一个socket,侦听这个端口。
DatagramSocket dsocket = new DatagramSocket(port);
byte[] buffer = new byte[2048]; // 保存接收到的UDP报文的字节数组
// 创建一个DatagramPacket,将收到的报文写入buffer中。
// 注意,这里指定了报文的长度,如果收到的UDP报文比2048大,
// 多余的信息被舍弃
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// 不断循环,接收数据
while (true) {
dsocket.receive(packet); // 等待收到一个数据包
// 将收到的报文的字节数组封装成字符串。
String msg = new String(buffer, 0, packet.getLength());
// 从数据包中取得消息来源的地址
System.out.println("Receive: "
+ packet.getAddress().getHostAddress() + ": " + msg);
// 如果收到QUIT指令,则退出循环。
if (msg.equalsIgnoreCase("QUIT")) {
System.out.println("退出UDP服务");
break;
}
packet.setLength(buffer.length); // 重设数据包的长度
}
// 关闭socket
dsocket.close();
} catch (Exception e) {
System.err.println(e);
// System.err.println(usage);
}
}
}
/**--------文件名:UDPClient.java-------------*/
class UDPClient {
public static void main(String args[]) {
try {
// 检查参数个数
if (args.length < 3) {
throw new IllegalArgumentException("参数个数有误");
}
// 域名和端口
String host = args[0];
int port = Integer.parseInt(args[1]);
// 下面构造待发送报文的字节数组
byte[] message;
if (args[2].equals("-f")) {
// 如果第三个参数为 -f,则表示将文件的内容以UDP方式发送
// 获得待发送的文件对象以及文件的长度
File f = new File(args[3]);
int len = (int) f.length();
// 创建一个足够容纳文件内容的字节数组
message = new byte[len];
FileInputStream in = new FileInputStream(f);
// 将文件内容以字节的方式读到字节数组中
int bytes_read = 0, n;
do {
n = in.read(message, bytes_read, len - bytes_read);
bytes_read += n;
} while ((bytes_read < len) && (n != -1));
} else {
// 如果第三个参数不是 -f,则将后面的参数当作消息发送
String msg = args[2];
for (int i = 3; i < args.length; i++) {
msg += " " + args[i];
}
message = msg.getBytes();
}
// 根据域名获取IP地址
InetAddress address = InetAddress.getByName(host);
// 初始化一个UDP包。
// DatagramPacket的构造方法中必须使用InetAddress,而不能是IP地址或者域名
DatagramPacket packet = new DatagramPacket(message, message.length,
address, port);
// 创建一个DatagramSocket,以发送UDP包
DatagramSocket dsocket = new DatagramSocket();
dsocket.send(packet);
System.out.println("send: " + new String(message));
dsocket.close();
// 注意:如果在构造DatagramPacket时,不提供IP地址和端口号,
// 则需要调用DatagramSocket的connect方法,否则无法发送UDP包
packet = new DatagramPacket(message, message.length);
dsocket = new DatagramSocket();
dsocket.connect(address, port);
dsocket.send(packet);
System.out.println("Send: " + new String(message));
dsocket.close();
} catch (Exception e) {
System.err.println(e);
}
}
}