实验六 多线程、网络编程
一、实验目的
1.掌握线程与网络编程的用法。
二、实验内容
1.键盘操作练习。掌握使用Thread的子类创建线程。编写一个JAVA应程序,在主线程中再创建两个线程,一个线程负责给出键盘上字母键上的字母,另外一个线程负责让用户在命令行中输入所给出的字母。
2.线程Thread-1。
3.线程Thread-11。
4.读取服务器端文件。
学会使用URL对象。创建一个URL对象,然后让URL对象返回输入流,通过该输入流读取URL所包含的资源文件。
5.会结帐的服务器。学会使用套接字读取服务器端的对象。客户端和服务器建立套字连接后,客户将账单发送给服务器。
三、实验步骤与实验结果
1.键盘操作练习
源代码:
package chapert1;
public class TypeKey {
public static void main(String args[]) {
System.out.println("键盘练习(输入#结束程序)");
System.out.printf("输入显示的字母(回车)\n");
Letter letter;
letter = new Letter();
GiveLetterThread giveChar;
InputLetterThread typeChar;
giveChar =new GiveLetterThread();
giveChar.setLetter(letter);
giveChar.setSleepLength(3200);
typeChar = new InputLetterThread();
typeChar.setLetter(letter);
giveChar.start();
typeChar.start();
}
}
package chapert1;
public class Letter {
char c ='\0';
public void setChar(char c) {
this.c = c;
}
public char getChar() {
return c;
}
}
package chapert1;
import java.awt.*;
import java.util.Scanner;
public class InputLetterThread extends Thread {
Scanner reader;
Letter letter;
int score = 0;
InputLetterThread() {
reader = new Scanner(System.in);
}
public void setLetter(Letter letter) {
this.letter = letter;
}
public void run() {
while(true) {
//System.out.printf("输入显示的字母(回车)\n");
String str = reader.nextLine();
char c = str.charAt(0);
if(c==letter.getChar()) {
score++;
System.out.printf("\t\t输入对了,目前分数%d\n",score);
}
else {
System.out.printf("\t\t输入错了,目前分数%d\n",score);
}
if(c=='#')
System.exit(0);
}
}
}
package chapert1;
public class GiveLetterThread extends Thread {
Letter letter;
char startChar ='a',endChar = 'z';
int sleepLength = 5000;
public void setLetter(Letter letter) {
this.letter = letter;
}
public void setSleepLength(int n){
sleepLength = n;
}
public void run() {
char c = startChar;
while(true) {
letter.setChar(c);
System.out.printf("显示的字符:%c\n ",letter.getChar());
try{
Thread.sleep(sleepLength); //【代码1】//调用sleep方法使得线程中断sleepLength豪秒
}
catch(InterruptedException e){}
c = (char)(c+1);
if(c>endChar)
c = startChar;
}
}
}
2.线程Thread-1
源代码:
package Thread_1;
//用Thread类的子类SpeakElephant、SpeakCar创建线程
public class Test1 {
public static void main(String[] args) {
SpeakElephant speakElephant = new SpeakElephant() ; //
SpeakCar speakCar = new SpeakCar(); //
speakElephant.start(); //开启线程,一定要调用start(),而不是调用run()
speakCar.start(); //
for(int i=1;i<=15;i++) {
System.out.println("main()"+i+" ");
}
}
}
package Thread_1;
public class SpeakElephant extends Thread{
public void run() {
for(int i=1;i<=20;i++) {
System.out.println("elephant"+i+" ");
}
}
}
package Thread_1;
public class SpeakCar extends Thread{
public void run() {
for(int i=1;i<=20;i++) {
System.out.println("car"+i+" ");
}
}
}
3.线程Thread-11
源代码:
package Thread_11;
//用Thread类创建线程
public class Test11 {
public static void main(String args[]) {
ElephantTarget elephant = new ElephantTarget();
CarTarget car = new CarTarget();
Thread speakElephant = new Thread(elephant) ; //elephant目标对象
Thread speakCar = new Thread(car); //car目标对象
speakElephant.start(); //
speakCar.start(); //
for(int i=1;i<=15;i++) {
System.out.println("main()"+i+" ");
}
}
}
package Thread_11;
public class ElephantTarget implements Runnable {
public void run() {
for(int i=1;i<=20;i++) {
System.out.println("elephant"+i+" ");
}
}
}
package Thread_11;
public class CarTarget implements Runnable {
public void run() {
for(int i=1;i<=20;i++) {
System.out.println("car"+i+" ");
}
}
}
4.读取服务器文件
源代码:
package chapert1;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import javax.swing.*;
public class ReadFile {
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);
String hostName = url.getHost();
int urlPortNumber= url.getPort();
String fileName=url.getFile();
InputStream in = url.openStream();
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;
}
}
}
5.会结帐的服务器
源代码:
package chapert2;
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);
}
catch(IOException e1) {
System.out.println("正在监听");
}
try{ System.out.println("正在等待客户");
you= server.accept();
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){}
}
}
package chapert2;
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();
OutputStream out= 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) {}
}
}
四、实验总结
通过本次实验明白了使用Thread子类创建线程,要注意父类的run()方法,学会使用了URL对象和网络套接字的对象;在实验的过程中,遇到了许多的问题,但认真的检查和查找资料就可以解决问题。