服务端详解:
服务端的主要功能就是无限监听一个端口号,对客户端发来的连接请求给予回应,然后开辟新线程处理客户端。界面做的比较简单就是显示在线的用户,分为商家和学生。
一.监听客户端的socket连接请求
<span style="font-family:KaiTi_GB2312;font-size:18px;">package mainjframe; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.Toolkit; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.LinkedList; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.DefaultTableModel; public class MainWindow extends JFrame{ ServerSocket server; JTable user_table; JTable seller_table; JScrollPane user_jscrollPane; JScrollPane seller_jscrollPane; DefaultTableModel user_model; DefaultTableModel seller_model; String []user_headers = {"序号","在线学生"}; String []seller_headers = {"序号","在线商家"}; Object [][]cellData=null; LinkedList<User> student,seller; LinkedList<Socket> mysocket; public static void main(String args[]) { new MainWindow("服务端"); } public MainWindow(String s) { super(s); student = new LinkedList<User>(); seller = new LinkedList<User>(); mysocket = new LinkedList<Socket>(); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } } ); //获取屏幕大小 Dimension screenSize =Toolkit.getDefaultToolkit().getScreenSize(); //设置窗体的位置和大小 setBounds((screenSize.width-320)/2,(screenSize.height-240)/2,320,240); setLayout(new GridLayout()); user_model = new DefaultTableModel(cellData,user_headers); user_table = new JTable(user_model); seller_model = new DefaultTableModel(cellData,seller_headers); seller_table = new JTable(seller_model); user_jscrollPane = new JScrollPane(user_table); user_jscrollPane.setPreferredSize(new Dimension(160, 240)); seller_jscrollPane = new JScrollPane(seller_table); seller_jscrollPane.setPreferredSize(new Dimension(160, 240)); add(user_jscrollPane); add(seller_jscrollPane); setVisible(true); validate(); startServer(); } void update() { user_model.setRowCount(0); seller_model.setRowCount(0); for(int i=0;i<student.size();i++) { user_model.addRow(new Object[]{i+1,student.get(i).account}); } for(int i=0;i<seller.size();i++) { seller_model.addRow(new Object[]{i+1,seller.get(i).account}); } } void startServer() { int i = 0; try { //设置监听端口号和最大接入数 server = new ServerSocket(8889, 3); System.out.println("==========start===========快点来啊"); new Thread(new ListenThread(this)).start(); while (true) { Socket socket = server.accept(); mysocket.add(socket); i++; System.out.println("第" + i + "个用户连接成功!"); System.out.println("该用户端的地址信息为:"+socket.getInetAddress()); new Thread(new ServerThread(socket,this)).start(); } } catch (IOException e) { e.printStackTrace(); } } } class ListenThread implements Runnable { private MainWindow mainWindow; public ListenThread(MainWindow mainWindow) { this.mainWindow = mainWindow; } public void run() { while(true) { for(int i=0;i<mainWindow.mysocket.size();i++) { if(mainWindow.mysocket.get(i).isClosed()) { for(int j=0;j<mainWindow.student.size();j++) { if(mainWindow.student.get(i).address == mainWindow.mysocket.get(i).getInetAddress()) mainWindow.student.remove(mainWindow.student.get(i)); } for(int j=0;j<mainWindow.seller.size();j++) { if(mainWindow.seller.get(i).address == mainWindow.mysocket.get(i).getInetAddress()) mainWindow.seller.remove(mainWindow.seller.get(i)); } mainWindow.update(); mainWindow.mysocket.remove(mainWindow.mysocket.get(i)); System.out.println("客户端已经断开"); } } try { Thread.sleep(500); } catch(Exception e) {} }} } </span>
在进程中使用while循环不断监听客户端发过来的请求,一旦请求建立成功就新建一个ServerThread子线程来处理客户端的请求,而主线程继续等待。同时开辟一个ListenThread线程不断判断哪一个线程已经断开连接。
二.在ServerThread中对客户端的请求进行处理
<span style="font-family:KaiTi_GB2312;font-size:18px;">package mainjframe; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; public class ServerThread implements Runnable { private Socket socket; private String accept; String account,passwd; DataInputStream in = null; DataOutputStream out = null; LinkMySql linkMySql; String dept; private MainWindow mainWindow; // 创建静态全局变量 public ServerThread(Socket socket,MainWindow mainWindow) { this.mainWindow = mainWindow; this.socket = socket; linkMySql = new LinkMySql(this); } // 任务是为一个用户提供服务 @Override public void run() { try { // 读取客户端传过来信息的DataInputStream in = new DataInputStream(socket.getInputStream()); // 向客户端发送信息的DataOutputStream out = new DataOutputStream(socket.getOutputStream()); System.out.println("放马过来吧!!!!"); // 读取来自客户端的信息 accept = in.readUTF(); System.out.println(accept); } catch (IOException e) { e.printStackTrace(); } if(accept.equals("LOGIN")) { try { account = in.readUTF(); passwd = in.readUTF(); System.out.println("用户名:"+account+"\n密码:"+passwd); for(int i=0;i<mainWindow.student.size();i++) { if(account.equals(mainWindow.student.get(i).account)) { socket.close(); } } for(int i=0;i<mainWindow.seller.size();i++) { if(account.equals(mainWindow.seller.get(i).account)) { socket.close(); } } dept = linkMySql.query(account,passwd); out.writeUTF(dept); if(dept.equals("student")) { User temp = new User(); temp.account = account; temp.passwd = passwd; temp.type = "student"; temp.address = socket.getInetAddress(); mainWindow.student.add(temp); mainWindow.update(); linkMySql.initStudent(in,out); linkMySql.handleOrder(); } else if(dept.equals("seller")) { User temp = new User(); temp.account = account; temp.passwd = passwd; temp.type = "seller"; temp.address = socket.getInetAddress(); mainWindow.seller.add(temp); mainWindow.update(); linkMySql.initseller(in,out); } } catch(IOException e) { } } else if(accept.equals("REGISTER")) { } } } </span>
先读取客户端发来的请求,然后进入对应的功能模块,如果是用户登录,则进行sql语句操作并对结果做出反应,如果查询错误则关闭该线程,判断为学生则加入学生链表并初始化学生端的商品信息和店铺信息,判断为商家则把改商家的商品信息发过去并查找相应的订单表,把属于该商家的订单发给商家。
服务端的主要功能就是利用socket和多线程把学生端和商家端连接起来,并把所有对数据的操作集中在服务端来做,全部由服务端与数据库进行交互,保证数据的安全。
时间: 2024-10-17 04:42:17