实验1 读取服务器端的文件
一、实验目的
学会使用URL对象
二、实验内容
创建一个URL对象,然后让URL对象返回输入流,通过该输入流读取URL所包含的资源文件。
三、程序代码
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import javax.swing.*;
public class ReadURLSource {
public static void main(String args[]) {
new NetWin();
}
}
class NetWin extends JFrame implements ActionListener,Runnable {
JButton button;
URL url;
JTextField inputURLText; //输入URL
JTextArea area;
byte b[]=new byte[118];
Thread thread;
NetWin() {
inputURLText=new JTextField(20);
area=new JTextArea(12,12);
button=new JButton("确定");
button.addActionListener(this);
thread=new Thread(this);
JPanel p=new JPanel();
p.add(new JLabel("输入网址:"));
p.add(inputURLText);
p.add(button);
add(area,BorderLayout.CENTER);
add(p,BorderLayout.NORTH);
setBounds(60,60,560,300);
setVisible(true);
validate();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e) {
if(!(thread.isAlive()))
thread=new Thread(this);
try{ thread.start();
}
catch(Exception ee) {
inputURLText.setText("我正在读取"+url);
}
}
public void run() {
try { int n=-1;
area.setText(null);
String name=inputURLText.getText().trim();
url = new URL(name);//使用字符串name创建url对象
String hostName = url.getHost();url调用getHost()
int urlPortNumber = url.getPort();
String fileName=url.getFile();
InputStream in = url.openStream();//url调用方法返回一个输入流
area.append("\n主机:"+hostName+"端口:"+urlPortNumber+
"包含的文件名字:"+fileName);
area.append("\n文件的内容如下:");
while((n=in.read(b))!=-1) {
String s=new String(b,0,n);
area.append(s);
}
}
catch(MalformedURLException e1) {
inputURLText.setText(""+e1);
return;
}
catch(IOException e1) {
inputURLText.setText(""+e1);
return;
}
}
}
四、实验指导
1、java.net包中的URL类是对统一资源定位符的抽象,使用URL创建对象的应用程序称作客户端程序,一个URL对象存放着一个具体的资源的引用,表明客户要访问这个URL中的资源,利用URL对象可以获取URL中的资源。
2、URL对象调用InputStream openStream()方法可以返回一个输入流,该输入流指向URL对象所包含的资源。通过该输入流可以将服务器上的资源信息读入到客户端。
3、URL资源的读取可能会引起阻塞,因此,程序需要在一个线程中读取URL资源,以免堵塞主线程。
实验2 会结帐的服务器
一、实验目的
学会使用套接字读取服务器端的对象
二、实验内容
客户端和服务器建立套接字连接后,客户将如下的账单发送给服务器:
房租:2189元 水费:112.9元 电费:569元 物业费:832元
服务器返回客户端的信息是:
您的账单
房租:2189元 水费:112.9元 电费:569元 物业费:832元
总计:3699.9元
三、程序代码
客户端:ClientItem.java
import java.io.*;
import java.net.*;
import java.util.*;
public class ClientItem {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
Socket clientSocket=null;
DataInputStream inData=null;
DataOutputStream outData=null;
Thread thread ;
Read read=null;
try{ clientSocket=new Socket();
read = new Read();
thread = new Thread(read); //负责读取信息的线程
System.out.print("输入服务器的IP:");
String IP = scanner.nextLine();
System.out.print("输入端口号:");
int port = scanner.nextInt();
String enter=scanner.nextLine(); //消耗回车
if(clientSocket.isConnected()){}
else{
InetAddress address=InetAddress.getByName(IP);
InetSocketAddress socketAddress=new InetSocketAddress(address,port);
clientSocket.connect(socketAddress);
InputStream in= clientSocket.getInputStream();//clientSocket调用getInputStream()返回该套接字的输入流
OutputStream out= clientSocket.getOutputStream();//clientSocket调用getOutputStream()返回该套接字的输出流
inData =new DataInputStream(in);
outData = new DataOutputStream(out);
read.setDataInputStream(inData);
read.setDataOutputStream(outData);
thread.start(); //启动负责读信息的线程
}
}
catch(Exception e) {
System.out.println("服务器已断开"+e);
}
}
}
class Read implements Runnable {
Scanner scanner = new Scanner(System.in);
DataInputStream in;
DataOutputStream out;
public void setDataInputStream(DataInputStream in) {
this.in = in;
}
public void setDataOutputStream(DataOutputStream out) {
this.out = out;
}
public void run() {
System.out.println("输入账单:");
String content = scanner.nextLine();
try{ out.writeUTF("账单"+content);
String str = in.readUTF();
System.out.println(str);
str = in.readUTF();
System.out.println(str);
str = in.readUTF();
System.out.println(str);
}
catch(Exception e) {}
}
}
服务器端:ServerItem.java
import java.io.*;
import java.net.*;
import java.util.*;
public class ServerItem {
public static void main(String args[]) {
ServerSocket server=null;
ServerThread thread;
Socket you=null;
while(true) {
try{ server= new ServerSocket(4331);//创建在端口4331上负责监听的 ServerSocket对象
}
catch(IOException e1) {
System.out.println("正在监听");
}
try{ System.out.println("正在等待客户");
you= server.accept();//server调用accept()返回和客户端相连接的Socket对象
System.out.println("客户的地址:"+you.getInetAddress());
}
catch (IOException e) {
System.out.println(""+e);
}
if(you!=null) {
new ServerThread(you).start();
}
}
}
}
class ServerThread extends Thread {
Socket socket;
DataInputStream in=null;
DataOutputStream out=null;
ServerThread(Socket t) {
socket=t;
try { out=new DataOutputStream(socket.getOutputStream());
in=new DataInputStream(socket.getInputStream());
}
catch (IOException e) {}
}
public void run() {
try{
String item = in.readUTF();
Scanner scanner = new Scanner(item);
scanner.useDelimiter("[^0123456789.]+");
if(item.startsWith("账单")) {
double sum=0;
while(scanner.hasNext()){
try{ double price = scanner.nextDouble();
sum = sum+price;
System.out.println(price);
}
catch(InputMismatchException exp){
String t = scanner.next();
}
}
out.writeUTF("您的账单:");
out.writeUTF(item);
out.writeUTF("总额:"+sum+"元");
}
}
catch(Exception exp){}
}
}
四、实验指导
1、套接字连接中涉及输入输出流操作,可能会引起堵塞,我们把读取数据放在一个单独的线程中去进行。另外服务器收到客户套接字后,就应该启动一个专门为该客户服务的线程。
2、Socket对象调用public void connect(SocketAddress endpoint)方法可以和参数endpoint指定的SocketAddress地址建立套接字连接。
实验3 TCP网络通信
一、实验目的
掌握TCP网络通信的相关类的使用
二、实验内容
1、编写服务器端程序:
(1)创建一个服务器套接字(ServerSocket),绑定到指定端口;
(2)调用accept方法,侦听来自客户端的请求,如果客户发出请求,则接受连接,返回通信套接字(Socket);
(3)创建线程来处理客户机:
- 在线程中调用getOutputStream方法,获得输入/输出流;
- 每连上一个客户端,就主动给客户端发送一句“欢迎光临!”
- 使用Arraylist存放连上服务端的所有客户端
- 当接收到客户端发送来的消息的时候,将这条消息转发给是有连上服务端的所有客户端
- 关闭通信套接字,
(4)关闭服务器套接字。
2、编写客户端程序:
(1)创建一个套接字(Socket), 向服务器的侦听端口发出请求;
(2)与服务器正确连接后,调用Socket的getlnputStream和getOutputStream方法,获得输入/输出流,启动线程开始网络数据的接收和发送;在命令行给服务端发送消息;当接收到服务端发来的消息的时候,将内容显示在控制台上
(3)关闭通信套接字
三、程序代码
客户端:TCPClient.java
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.List;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JFrame;
public class TCPClient extends JFrame {
Socket s = null;
DataOutputStream dos = null;
DataInputStream dis = null;
TextField tf = new TextField(40);
List list = new List(10);
public static void main(String[] args) {
TCPClient client = new TCPClient();
client.list.add("向服务器端发送的数据:");
client.setTitle("客户端");
client.run();
}
public void run() {
setLocation(400, 300); // 设置窗体的位置
this.setSize(300, 300); // 设置窗体的大小
add(tf, BorderLayout.SOUTH);
add(list, BorderLayout.NORTH);
pack(); //调整此窗口的大小,以适合其子组件的首选大小和布局。
this.addWindowListener(new WindowAdapter() { // 关闭窗体
public void windowClosing(WindowEvent e) {
disconnect();
System.exit(0);
}
});
tf.addActionListener(new MyListener()); // 注册事件监听器
setVisible(true);
connect();
}
public void connect() {
try {//139.155.5.93
s = new Socket("127.0.0.1", 8866); // 创建一个向服务器发起连接的Socket对象
dos = new DataOutputStream(s.getOutputStream());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void disconnect() {
try {
dos.close(); // 关闭输出流
s.close(); // 关闭Socket对象
} catch (IOException e) {
e.printStackTrace();
}
}
private class MyListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String s1 = null;
String s2 = null;
String str = tf.getText().trim(); // 获取文本框中的内容
list.add(str);
tf.setText(""); // 将文本框的内容清空
try {
dos.writeUTF(str); // 向流中写入数据
dos.flush(); // 刷空流
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
服务器端:TCPServer.java
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.TextArea;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JFrame;
public class TCPServer {
static DataInputStream dis = null;
public static void main(String[] args) {
boolean started = false;
Socket s = null;
TextArea ta = new TextArea();
ta.append("从客户端接收的数据:"+"\n");
ServerSocket ss = null;
try {
ss = new ServerSocket(8866); // 创建一个监听Socket对象
} catch (BindException e) {
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
JFrame f = new JFrame("服务器端");
f.setLocation(300, 300);
f.setSize(200, 200);
f.add(ta, BorderLayout.NORTH);
f.pack();
f.addWindowListener(new WindowAdapter() { // 关闭窗口
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setVisible(true); // 设置窗体可见
try {
started = true;
while (started) {
boolean bConnected = false;
s = ss.accept(); // 等待客户端请求连接
bConnected = true;
dis = new DataInputStream(s.getInputStream());
while (bConnected) {
String str =s.getRemoteSocketAddress()+":"+ dis.readUTF(); // 从输入流中读取数据
ta.append(str+"\n"); // 将数据添加到文本区中
}
}
} catch (EOFException e) {
System.out.println("Client closed!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (dis != null)
dis.close(); // 关闭输入流
if (s != null)
s.close(); // 关闭Socket对象
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
实验4 UDP网络通信
一、实验目的
掌握UDP网络通信的相关类的使用
二、程序代码
发送端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class SX10C {//主类
public static void main(String[] args) {//主方法
Scanner input=new Scanner(System.in);
System.out.print("这里是发送端,请输入要发送的数据:");
String info1 = input.nextLine();
input.close();
try {
//创建发送端 Socket,使用4567端口
DatagramSocket socket = new DatagramSocket(4567);
String info2 = "接收端你好,我是发送端";
byte[] buf=info2.getBytes();
//指明接收端的IP和端口号。演练时请注意更换成实际IP
InetAddress ip=InetAddress.getByName("192.168.0.104");
DatagramPacket pcket = new DatagramPacket(buf,buf.length,ip,3456);
socket.send(pcket);//从此套接字中发送数据
displayRecInfo(socket); //调用displayRecInfo()方法显示结果
}
catch(Exception ex) {
System.out.println(ex.toString());
}
}
//用于在控制台中显示结果的diplayRecInfo()方法
public static void displayRecInfo(DatagramSocket s)throws IOException {
byte[] buffer =new byte[1024]; //定义用于存储数据的字节数组
DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
s.receive(packet);
byte[] data = packet.getData();
InetAddress ip=packet.getAddress();
System.out.println("接收端的回应:"+new String(data));
System.out.println("接收端的IP:"+ip.toString());
System.out.println("接收端的端口:"+packet.getPort());
}
}
接收端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class SX10S {
static boolean isRun = true;
public static void main(String[] arg) {
System.out.println("-_接收端启动成功一 ");
try {
//演练时请注意将IP地址更换成实际IP
InetAddress ip = InetAddress.getByName("192.168.0.104");
DatagramSocket socket = new DatagramSocket(3456,ip);
byte[] buf = new byte[1024];
//创建接收数据包,数据存储在buf中
DatagramPacket packet1 = new DatagramPacket(buf, buf.length);
while(isRun) { //接收操作,接收端循环操作,跳出循环将停止接收信息
socket.receive(packet1);
System.out.println("---接收端收到数据一 ");
displayRecInfo(packet1);
String temp = "";
byte[] d = packet1.getData();
if(!new String(d).toString().trim().equals("bye")) {
//如果接收到的不是bye
temp = "我是接收端,你发送的数据以收到";
}else {
temp = "好吧,再见";
isRun = false; //若接收的信息是bye,则退出循环,不再接收数据
}
byte[] buffer = temp.getBytes();
//创建数据报,指定需要反馈给发送者的SocketAddres地址
DatagramPacket packet2 =
new DatagramPacket(buffer, buffer.length, packet1.getSocketAddress());
socket.send(packet2);
}
socket.close();
}
catch(Exception ex) {
System.out.println(ex.toString());
}
}
public static void displayRecInfo(DatagramPacket p) throws IOException{//显示数据的方法
byte[] data = p.getData();
InetAddress ip = p.getAddress();//发送者的地址
//trim()方法用于除去空元素
System.out.println("收到的消息:" + new String(data).trim());
System.out.println("发送者的IP:" + ip.toString());
System.out.println("发送者的端口号:"+ p.getPort());
}
}