Java学习笔记(3)----网络套接字服务器多线程版本
本例给出一个客户端程序和一个服务器程序。客户端向服务器发送数据。服务器接收数据,并用它来生成一个结果,然后将这个结果返回给客户端。客户端在控制台上显示结果。在本例中,客户端发送的数据是圆的半径,服务器生成的结果是圆的面积。
客户端通过输出流套接字的 DataOuputStream 发送半径,服务器通过输入流套接字的 DataInputStream 接收半径。服务器计算面积,然后,通过输出流套接字的 DataOutputStream 把它发送给客户端,客户端通过输入流套接字的 DataInputStream 接收面积。服务器和客户端程序在下面的程序清单中给出。
//Server.java
package src; import java.awt.BorderLayout; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; public class Server extends JFrame { private JTextArea jta=new JTextArea(); private ExecutorService executor=Executors.newCachedThreadPool(); public static void main(String[] args){ new Server(); } public Server(){ setLayout(new BorderLayout()); add(new JScrollPane(jta),BorderLayout.CENTER); setTitle("Server"); setSize(500, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); try{ ServerSocket serverSocket=new ServerSocket(8000); jta.append("Server started at "+new Date()+'\n'); while(true){ Socket socket=serverSocket.accept(); executor.execute(new Task(socket)); //对接收到的新的连接,启动一个新的线程 } } catch(IOException ex){ System.err.println(ex); } finally{ executor.shutdown(); } } private class Task implements Runnable{ private Socket socket; public Task(Socket socket){ this.socket=socket; } @Override public void run() { //在线程中执行对客户端的应答 // TODO Auto-generated method stub try{ DataInputStream inputFromClient=new DataInputStream(socket.getInputStream()); DataOutputStream outputToClient=new DataOutputStream(socket.getOutputStream()); while(true){ double radius=inputFromClient.readDouble(); double area=radius*radius*Math.PI; outputToClient.writeDouble(area); jta.append("######## From client -["+socket.getInetAddress()+":"+socket.getPort()+"]-Radius = "+radius+"\n"); jta.append("******** Area is---- "+area+'\n'); } } catch(IOException ex){ System.err.println(ex); } } } }
//Client.java
package src; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; public class Client extends JFrame { private JTextField jtf=new JTextField(); private JTextArea jta=new JTextArea(); private DataOutputStream toServer; private DataInputStream fromServer; private Socket socket; public static void main(String args[]){ new Client(); } public Client(){ JPanel panel=new JPanel(); panel.setLayout(new BorderLayout()); panel.add(new JLabel("Enter radius"),BorderLayout.WEST); panel.add(jtf, BorderLayout.CENTER); jtf.setHorizontalAlignment(JTextField.RIGHT); setLayout(new BorderLayout()); add(panel,BorderLayout.NORTH); add(new JScrollPane(jta), BorderLayout.CENTER); jtf.addActionListener(new TextFieldListener());//some thing wrong setTitle("Client"); setSize(500, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); try{ socket=new Socket("localhost",8000); fromServer=new DataInputStream(socket.getInputStream()); toServer=new DataOutputStream(socket.getOutputStream()); } catch(IOException ex){ jta.append(ex.toString()+'\n'); } } private class TextFieldListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub try{ double radius=Double.parseDouble(jtf.getText().trim()); toServer.writeDouble(radius); toServer.flush(); double area=fromServer.readDouble(); jta.append("----------- Radius is "+radius+'\n'); jta.append("$$$$$$$$$$$ From server -["+socket.getInetAddress()+":"+socket.getPort()+"] Area= "+area+'\n'); } catch(IOException ex){ System.err.println(ex); } } } }
运行效果: