实验3 TCP网络编程
需要详细文档资料见文章末尾
一、实验目的:
1、熟悉TCP网络编程的一般操作。
2、理解多线程的作用。
3、理解ArrayList集合类的作用。
4、理解事件处理机制。
5、了解swing编程。
二、 实验内容:
1、通过TCP网络编程实现:每次运行客户端,都能够从服务器中获得不同的诗歌的名字。请在【代码一】~【代码五】
填写代码。
(1)新建名为”ex3”的项目(Java应用程序)。在项目中,新建Java类,命名为“DailyPoetryClient”。在DailyPoetryClient.java文件中,定义客户端类。客户端类的主要功能:打印输出从服务器中读取的诗歌名。
import java.io.*;
import java.net.*;
public class DailyPoetryClient {
public void go() {
try {
Socket s = new Socket("127.0.0.1",5000);
//【代码一】
System.out.println("Today's Poetry: "+poetry);
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
DailyPoetryClient client = new DailyPoetryClient();
client.go();
}
}
(2)在项目中,新建Java类,命名为“DailyPoetryServer”。在DailyPoetryServer.java文件中,定义服务器类。服务器类的主要功能:向客户端随机输出一首诗歌名。
import java.net.*;
import java.io.*;
public class DailyPoetryServer {
String [] poetrys = {"太阳颂","生如夏花","飞鸟集","园丁集","吉檀迦利","闲暇"};
public void go() {
try {
/*【代码二】*/;
//【代码三】
PrintWriter writer = new PrintWriter(sock.getOutputStream());
String poetry = getPoetry(); //获取诗歌名
//【代码四】
sock.close();
System.out.println(poetry);
} catch (Exception e) {
e.printStackTrace();
}
}
//随机返回诗歌名
private String getPoetry() {
int random = (int)(Math.random()*poetrys.length);
/*【代码五】*/;
}
public static void main(String [] args) {
DailyPoetryServer server = new DailyPoetryServer();
server.go();
}
}
2、通过多线程编程,改写服务器类DailyPoetryServer,以实现该服务器能同时服务多个客户端。
【说明】在项目中,新建Java类,命名为“DailyPoetryServer2”。在DailyPoetryServer2.java文件中,定义多线程的服务器类DailyPoetryServer2。
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class DailyPoetryServer2 {
String[] poetrys = {"太阳颂", "生如夏花", "飞鸟集", "园丁集", "吉檀迦利", "闲暇"};
public void go() {
try {
ServerSocket serverSocket = new ServerSocket(5000);
System.out.println("服务器已启动,等待客户端连接...");
while (true) {
Socket sock = serverSocket.accept();
Thread clientHandler = new ClientHandler(sock);
clientHandler.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private String getPoetry() {
int random = (int) (Math.random() * poetrys.length);
return poetrys[random];
}
public static void main(String[] args) {
DailyPoetryServer2 server = new DailyPoetryServer2();
server.go();
}
private class ClientHandler extends Thread {
private Socket clientSocket;
public ClientHandler(Socket socket) {
this.clientSocket = socket;
}
@Override
public void run() {
try {
PrintWriter writer = new PrintWriter(clientSocket.getOutputStream(), true);
String poetry = getPoetry();
writer.println(poetry);
System.out.println("已发送诗歌给客户端: " + poetry);
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3、创建简单的TCP聊天程序。
(1)在项目中,新建Java类,命名为“SimpleChatClient”。在SimpleChatClient.java文件中,定义客户端类。客户端类的主要功能:实现聊天界面,当用户在文本框中输入一行文本,单击“发送”按钮,文本信息将传送给服务器。
import java.io.*;
import java.net.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleChatClient {
JTextArea incoming;
JTextField outgoing;
BufferedReader reader;
PrintWriter writer;
Socket socket;
public static void main(String[] args) {
new SimpleChatClient().go();
}
public void go() {
JFrame frame = new JFrame("聊天客户端");
JPanel mainPanel = new JPanel();
JPanel panel = new JPanel();
incoming = new JTextArea(15, 30);
incoming.setLineWrap(true);//设置在行过长的时候是否要自动换行
incoming.setWrapStyleWord(true);//设置在单词过长的时候是否要把长单词移到下一行。
incoming.setEditable(false);
JScrollPane qScrollPane = new JScrollPane(incoming);
qScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
qScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
outgoing = new JTextField(20);
JButton sendButton = new JButton("发送");
//设置按钮的监听器
sendButton.addActionListener(new SendButtonListener());
panel.add(outgoing);
panel.add(sendButton);
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.add(qScrollPane);
mainPanel.add(panel);
frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//窗体关闭,则退出应用程序
frame.setResizable(false); //禁止改变窗体大小
frame.pack();
frame.setVisible(true);
frame.getRootPane().setDefaultButton(sendButton);
//设置在窗口中按下回车键时,单击了sendButton
setUpNetWoking();//连接服务器
//创建一个线程,用于接收服务器的消息
Thread readerThread = new Thread(new IncomingReader());
readerThread.start();
}
//将“发送”按钮的事件处理类定义为内部类
public class SendButtonListener implements ActionListener {
public void actionPerformed(ActionEvent ev) {
//请手动输入代码
try {
writer.println(outgoing.getText());
writer.flush();
} catch (Exception e) {
e.printStackTrace();
}
//清空文本框
outgoing.setText("");
outgoing.requestFocus();
}
}
private void setUpNetWoking() {
//请手动输入代码
try {
socket = new Socket("127.0.0.1",5000);
InputStreamReader streamReader = new InputStreamReader(socket.getInputStream());
reader = new BufferedReader(streamReader);
writer = new PrintWriter(socket.getOutputStream());
System.out.println("networking established");
} catch (IOException e) {
e.printStackTrace();
}
}
//将接收服务器端消息的线程定义为内部类
public class IncomingReader implements Runnable {
//请手动输入代码
@Override
public void run() {
String message;
try {
while ((message = reader.readLine()) != null){
System.out.println("read:"+message);
incoming.append(message+"\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void actionPerformed((ActionEvent ev)的实现代码:
setUpNetWoking()的实现代码如下:
IncomingReader类的实现代码如下:
(2)在项目中,新建Java类,命名为“SimpleChatServer”。在SimpleChatServer.java文件中,定义服务器类。服务器的主要功能:将接收到的信息,群发给所有的客户端。
import java.io.*;
import java.net.*;
import java.util.*;
public class SimpleChatServer {
ArrayList<PrintWriter> clientOutputStreams;
public static void main(String[] args) {
new SimpleChatServer().go();
}
public void go() {
//请手动输入代码
clientOutputStreams = new ArrayList<>();
try {
ServerSocket serverSocket = new ServerSocket(5000); // 服务器监听的端口
System.out.println("服务器已启动,等待客户端连接...");
while (true) {
Socket clientSocket = serverSocket.accept(); // 接受客户端连接
PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
clientOutputStreams.add(writer);
Thread t = new Thread(new ClientHandler(clientSocket));
t.start();
System.out.println("客户端已连接");
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public class ClientHandler implements Runnable {
BufferedReader reader;
Socket socket;
public ClientHandler(Socket clientSocket) {
//请手动输入代码
try{
socket = clientSoket;
InputStreamReader isReader=new InputStreamReader(socket.getInputStream());
reader = new BufferedReader(isReader);
}catch(IOException e){
e.printStackTrace();
}
}
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("read: " + message);
tellEveryone(message);
}
} catch (Exception ex) {
//ex.printStackTrace();
}
}
}
public void tellEveryone(String message) {
//请手动输入代码
Iterator<PrintWriter> it = clientOutputStreams.iterator();
while (it.hasNext()){
try {
PrintWriter writer = it.next();
writer.println(message);
writer.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public void go()的实现代码:
public ClientHandler(Socket clientSocket)的定义:
public void tellEveryone(String message)的定义:
实验具体实现
import java.io.*;
import java.net.*;
public class DailyPoetryClient {
public void go() {
try {
Socket s = new Socket("127.0.0.1",5000);
//【代码一】
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
String poetry = reader.readLine();
System.out.println("Today's Poetry: "+poetry);
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
DailyPoetryClient client = new DailyPoetryClient();
client.go();
}
}
import java.net.*;
import java.io.*;
public class DailyPoetryServer {
String [] poetrys = {"太阳颂","生如夏花","飞鸟集","园丁集","吉檀迦利","闲暇"};
public void go() {
try {
ServerSocket serverSocket = new ServerSocket(5000)/*【代码二】*/;
//【代码三】
Socket sock = serverSocket.accept();
PrintWriter writer = new PrintWriter(sock.getOutputStream());
String poetry = getPoetry(); //获取诗歌名
writer.println(poetry);
//【代码四】
sock.close();
System.out.println(poetry);
} catch (Exception e) {
e.printStackTrace();
}
}
//随机返回诗歌名
private String getPoetry() {
int random = (int)(Math.random()*poetrys.length);
return poetrys[random]/*【代码五】*/;
}
public static void main(String [] args) {
DailyPoetryServer server = new DailyPoetryServer();
server.go();
}
}