`
NX
  • 浏览: 12221 次
  • 性别: Icon_minigender_2
社区版块
存档分类
最新评论
  • smartan: 话说这就是所谓的以时间换空间吧
    队列
  • NX: 是的,真心感谢各位提出的意见和建议,我也在修改代码,主要是在怎 ...
    队列
  • xchd: 队列不是先进先出吗?好像没有体现这点。
    队列
  • kidding87: 你这里应该和jdk学习下,动态的容量,怎么去扩容,你这里效率非 ...
    队列

通信之c/s简单交互

阅读更多

  

     就目前我们做的c/s的简单交互而言主要用到了三个类:客户端线程类ClientThread    服务端监听类ChatServer  服务端线程类ChatThread

     简单理解:通过socket建立客户端与服务器的连接,在客户端和服务器分别用输入输出流来获得和写出消息,通过消息的传递达到交互的目的。

ps: socket 实现客户端套接字  套接字是两台机器间通信的端点)

打开输入输出流(用字符流封装)
       InputStream in = socket.getInputStream();
       OutputStream out = socket.getOutputStream();
 //将字节流转成字符流                 
       reader = new BufferedReader(new InputStreamReader(in, "GB2312"));
       writer = new BufferedWriter(new OutputStreamWriter(out, "GB2312"));
 
//读消息(线程循环读取)
            while(line != null){
                 line  = reader.readLine();
                         }
 
//发送消息
          writer.write(msg); writer.flush();

 

 

     客户端  登陆界面类LoginUI  客户消息处理线程类ClientThread   聊天界面类ClientUI

 

(1)登陆界面:主要是用来创建一个登陆的窗口,获得用户名以及密码

 

package 1;
/**
 * (1)
 */
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
 
public class LoginUI extends JFrame{
     
      private ClientThread ct;
     
      //入口函数
      public static void main(String args[]){
             LoginUI loginUI = new LoginUI();
             loginUI.init();
      }
     
      public void init(){
              //创建一个登陆界面
             this.setTitle("登陆界面");
             this.setSize(200,200);
             this.setResizable(false);
             this.setDefaultCloseOperation(3);
             this.setLayout(new FlowLayout());
            
             //创建标签
             JLabel jb1 = new JLabel("用户名:");
             this.add(jb1);
            
             //创建文本输入框
             final JTextField username = new JTextField(10);
             this.add(username);
            
             JLabel jb2 = new JLabel("密    码:");
             this.add(jb2);
            
             final JPasswordField  passwd = new JPasswordField(10);
             this.add(passwd);
            
             //创建一个按钮对象
             JButton jb3 = new JButton("登陆");
             this.add(jb3);
             jb3.setActionCommand("login");
             //给按钮添加监听器(内部类)
             jb3.addActionListener(new ActionListener(){
                    
                     public void actionPerformed(ActionEvent e) {
                              //创建一个用户线程,在构造函数中传入界面对象(LoginUI.this)!!!!!!!!!!!!! 、ip、端口号、用户名、密码
                             ct = new ClientThread(LoginUI.this,"127.0.0.1",8008,username.getText(),passwd.getText());
                             //启动线程
                             Thread th = new Thread(ct);
                             th.start();
                     }
             });
            
         this.setVisible(true);     
      }
 
      public void LoginResult(boolean result){
             if(result == false){
                     //JOptionPane 有助于方便地弹出要求用户提供值或向其发出通知的标准对话框   (静态方法直接用类名调用)
                     JOptionPane.showMessageDialog(this,"登陆失败!!哈哈哈哈。。。");
             }else{
                     //登陆界面消失
                     this.dispose();
                     //创建一个聊天窗口
                     ClientUI  ui = new ClientUI(ct);
                     ui.init();
                     //将窗口作为参数传给用户处理线程
                     ct.setClientUI(ui);
             }
      }
}

 

 

(2)线程类:将登陆结果返回给登陆界面、将服务器传送来的消息发给聊天界面对象

package  1;
 
/**
 * 用户登陆处理线程    (2)
 
 */
 
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
 
import javax.swing.JFrame;
 
public class ClientThread extends JFrame implements Runnable{
      private LoginUI loginUI;
      private String ip;
      private int port;
      private String username;
      private String passwd;
      private ClientUI ui;
     
      private Socket socket;
     
      private BufferedWriter writer;
      private BufferedReader reader;
      private boolean runFlag = true;
      private boolean isLogin = false;
     
      //重载构造函数
      public ClientThread(LoginUI loginUI,String ip,int port,String username,String passwd){
             this.loginUI = loginUI;
             this.ip = ip;
             this.port = port;
             this.username = username;
             this.passwd = passwd;
      }
     
   //得到用户聊天界面对象
      public void setClientUI(ClientUI ui){
             this.ui = ui;
      }
     
      public boolean connectServer(){
             try {
                     //创建一个套接字
                     socket = new Socket(ip,port);
                    
                     //得到输入输出流对象
                     InputStream in = socket.getInputStream();
                     OutputStream out = socket.getOutputStream();
                    
                     //将字节流转成字符流
                     reader = new BufferedReader(new InputStreamReader(in, "GB2312"));
                     writer = new BufferedWriter(new OutputStreamWriter(out, "GB2312"));
                     return true;
             } catch (UnknownHostException e) {
                     e.printStackTrace();
             } catch (IOException e) {
                     e.printStackTrace();
             }
                 return false;
      }
     
      public void run(){
             if(connectServer() == false){
                     System.out.println("登陆服务器失败!");
                     return;
             }
            
             login();
            
             if(isLogin == false){
                     return;
             }
            
            
             String msg;
             try {
                     //通过读入流获得消息
                     msg = reader.readLine();
                     while(runFlag && msg != null){
                             //将消息发送给聊天界面
                             ui.onMsg(msg);
                             msg = reader.readLine();
                     }
             } catch (IOException e) {
                     e.printStackTrace();
             }
             System.out.println("ClientThread退出来了");
             }
     
     
      public void sendMsg(String msg){
             try {
                     writer.write(msg+"\r\n");
                     writer.flush();
             } catch (IOException e) {
                     e.printStackTrace();
             }
      }
     
      public void login(){
             try {
                    
                     writer.write(username+"\r\n");
                     writer.write(passwd+"\r\n");
                     writer.flush();
                    
                     String result = reader.readLine();
                     if("LoginOK".equals(result)){
                             System.out.println("登陆成功!");
                             isLogin = true;
                             //创建一个新的聊天界面
                             loginUI.LoginResult(true);
                     }else{
                             System.out.println(result);
                             //弹出一个窗口显示登陆失败了
                             loginUI.LoginResult(false);
                     }
                    
             } catch (IOException e) {
                     e.printStackTrace();
             }
            
      }
      }
 
 

 

(3)聊天界面类:将消息显示在指定区域。

package  1;
 
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
 
public class ClientUI extends JFrame{
             //声明一个线程
      private ClientThread ct;
       
      public ClientUI(ClientThread ct){
                     this.ct = ct;
      }
 
      //创建一个指定行列的空文本域   “聊区”
      JTextArea logArea = new JTextArea(13,40);
     
     
     
      public void init(){
             //创建聊天窗口
             this.setTitle("聊吧");
             this.setSize(500,400);
             this.setResizable(false);
             this.setDefaultCloseOperation(3);
             this.setLayout(new FlowLayout());
            
            
             this.add(logArea);
            
             //创建一个指定行列的文本域   “发送消息区”
             final JTextArea sendMsg = new JTextArea(4,40);
             this.add(sendMsg);
            
            
             //创建一个发送按钮
             JButton jb1 = new JButton("发送");
             this.add(jb1);
             
            
             jb1.addActionListener(new ActionListener(){
 
                     public void actionPerformed(ActionEvent e) {
                              //发送文本区的内容
                             String msg = sendMsg.getText().toString();
                             //线程将消息发送过来
                             ct.sendMsg(msg);
                             //将发送区清空
                             sendMsg.setText("");
                             }
             });
            
             this.setVisible(true);
            
      }
 
 
              //接受服务器发送过来的消息
             public  void onMsg(String msg ){
                     //将消息显示在“聊吧”界面的聊天区
                             logArea.setText(logArea.getText()+msg+"\r\n");
             }
}

 

 

    服务端 服务端监听类ChatServer  服务端线程类ChatThread  、用户存储队列ChatTools、用户数据类DateTools

(1)监听类的作用:监听端口 (监听一个端口号,等待用户的访和  创建一个服务端线程对象 

package  1;
/**
 * (1)
 */
import java.io.IOException;
 
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
 
public class ChatServer {
 
      public static void main(String[] args) {
            
             new ChatServer().setupServer(8008);
      }
     
     
      public void setupServer(int port) {
             try {
                     //监听一个端口号码,等待用户的访问
                     ServerSocket ss = new ServerSocket(port);
            
                     //循环等待客户端的访问
                     while(true){
                              //得到socket
                             Socket socket = ss.accept();
                              
                             //将socket传给服务端线程进行处理
                             ChatThread ct = new ChatThread(socket);
                             //启动线程
                             ct.start();
                          }         
                } catch (IOException e) {
                     e.printStackTrace();
                        }
        }
 
}

 

 

(2)线程类的作用:打开输入输出流(用字符流封装)  读消息(线程循环读取)、  处理消息、  发送消息给登录界面(不需要线程)、创建一个队列保存所有用户信息 

package  1;
/**
 * (2)
 */
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
 
public class ChatThread extends Thread {
      private Socket socket;
      private String username;
      private boolean isLogin = false;
      private BufferedWriter writer;
      private BufferedReader reader;
     
      public ChatThread(Socket socket){
             this.socket = socket;
      }
     
      public void run() {
             try {
                     InputStream in = socket.getInputStream();
                     OutputStream out = socket.getOutputStream();
                    
                     //将字节流转成字符流
                     reader = new BufferedReader(new InputStreamReader(in, "GB2312"));
                     writer = new BufferedWriter(new OutputStreamWriter(out, "GB2312"));
                    
                     login();
                     //将登录成功的用户添加到在线用户队列
                     ChatTools.addClient(this);
                    
                     String line  = reader.readLine();
                     while(line != null){
                             ChatTools.castMsg(username +"说:"+line);
                             line  = reader.readLine();
                     }
                     close();
                      //ChatTools.castMsg(username +"走了");
                                    } catch (Exception e) {
                     close();
                     e.printStackTrace();
             }
            
      }
     
      private void login() throws IOException {
             String msg = null;
             while(isLogin == false){
                    
                     String username = reader.readLine();
                     String passwd = reader.readLine();
                      
                     //从数据库中取密码
                     String passwd2 = DateTools.getPasswd(username);
                     //如果为null,说明数据库里面没有该用户
                     if(passwd2 == null){
                             msg = "用户不存在\r\n";
                             writer.write(msg);
                             writer.flush();
                     } else {
                             if(passwd2.equals(passwd)){
                                    isLogin = true;
                                    this.username = username;
                             }
                     }
                     if(isLogin == false){
                             msg = "密码错误!\r\n";
                             writer.write(msg);
                             writer.flush();
                     }
             }
             //给用户登陆界面一个信号,决定其下一步是弹出“登录失败”还是一个新的聊天窗口
             msg = "LoginOK\r\n";
             writer.write(msg);
             writer.flush();
      }
     
      public void sendMsg(String msg) {
             try {
                     writer.write(msg);
                     writer.flush();
             } catch (IOException e) {
                     e.printStackTrace();
             }
            
      }
     
 
      public String getUsername() {
             return username;
      }
     
      public void close() {
             try {
                     ChatTools.remove(this);
                     socket.close();
             } catch (IOException e) {
                     e.printStackTrace();
             }
      }
}

 

 (4)用户存储队列ChatTools :将登录成功的用户加入到队列中(代码略)

     

 (5)用户数据类DateTools  创建一个哈希表(key,value),将指定值存入。(代码略)

     

 

0
0
分享到:
评论

相关推荐

    利用Java Sock实现C/S通信

    下面将详细介绍Java Socket在C/S通信中的应用,以及如何构建这样的系统。 一、Java Socket基础 1. Socket概念:Socket在计算机网络中是一种进程间通信机制,它提供了一种在网络上的两个进程之间建立和维护连接的...

    C/S聊天程序(JAVA,C/S)

    1. **Socket编程**:Java的`java.net.Socket`和`ServerSocket`类是实现C/S通信的基础。服务器端创建`ServerSocket`监听特定端口,等待客户端的连接请求;客户端使用`Socket`连接到服务器,建立通信通道。 2. **多...

    vb 编写的c/s简单通信程序

    本项目名为"vb 编写的c/s简单通信程序",其核心是实现基本的TCP(Transmission Control Protocol)网络通信,这是网络通信的基础。 TCP是一种面向连接的、可靠的传输协议,它确保了数据的完整性和顺序,适合于需要...

    C/S构架的网络通信程序

    在" C/S构架的网络通信程序 "这个主题中,我们将深入探讨C#语言下如何利用Socket库来实现基于TCP协议的可靠网络通信。 TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的...

    B/S与C/S的比较

    C/S架构指的是客户端(Client)与服务器(Server)之间的架构模式,这是一种分布式软件架构,其中客户端负责提供用户交互界面以及执行一部分业务逻辑,而服务器端则主要负责数据存储管理和复杂业务逻辑处理。 - **特点*...

    c/s 架构的通信技术

    C/S(Client/Server)架构是一种常见的软件系统架构模式,其中客户端(Client)与服务器端(Server)通过网络进行通信,以实现数据的交互和处理。在这个架构中,客户端是用户直接操作的部分,负责用户界面的展示和...

    netty框架各种通信C/S端

    在这个"Netty框架各种通信C/S端"的资源中,包含了使用Netty实现客户端(Client)和服务器(Server)通信的实例。 1. **TCP通信**: TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的...

    C/S模式下的java图书管理系统

    C/S(Client/Server)模式是一种常见的软件架构模式,它将应用逻辑分为客户端(Client)和服务器端(Server)两部分,客户端负责用户交互,服务器端则处理数据存储和管理。在这个场景中,我们讨论的是一个基于Java...

    c++ c/s通信

    C/S通信,即客户端/服务器通信,是网络编程中的基本模式,通常用于构建分布式系统。在这个场景下,C++可以用来编写服务器和客户端应用程序,实现数据的交互。 在C/S通信中,服务器端负责监听客户端的连接请求,并对...

    基于TCP的C/S简单Swing通信

    在"基于TCP的C/S简单Swing通信"项目中,Swing被用来构建客户端的用户界面,用户可以通过界面发送和接收数据。TCP协议则用于客户端和服务器之间的数据传输。Swing组件如按钮、文本框等可以与TCP连接事件绑定,当用户...

    三层架构工作流程图B/S架构及C/S架构

    三层架构是一种常见的软件设计模式,尤其在B/S(Browser/Server)和C/S(Client/Server)架构中广泛应用。这种架构将应用分为三个主要部分:表现层(Presentation Layer)、业务逻辑层(Business Logic Layer)和...

    B/s和C/S的区别

    C/S 结构软件测试的优点是可以更好地测试客户端和服务器端的交互,发现问题的原因和解决方法。但是,C/S 结构软件测试也存在一些缺点,例如需要多台机器和网络环境,测试过程复杂。 二、B/S 结构软件测试 B/S 结构...

    基于C/S模式的网络通信

    在C/S模式下,客户端负责用户交互,而服务器端则处理客户端请求并提供服务。本主题将深入探讨如何利用C#语言在.NET框架下实现C/S模式的网络通信。 首先,我们要理解C#中的网络通信基础。C#提供了丰富的类库,如...

    基于C/S模式的员工管理系统

    在C/S模式下,客户端主要负责数据展示、用户交互和部分简单计算,而服务器端则承担数据存储、复杂业务逻辑处理以及多客户端同步协调的任务。这样的设计确保了系统的稳定性和数据的安全性,同时,由于客户端与服务器...

    使用Qt Creator编写基于C/C++的局域网通信(C/S)程序(Linux平台)

    在本文中,我们将深入探讨如何使用Qt Creator在Linux平台上编写基于C/C++的局域网通信(C/S)程序。Qt Creator是一个强大的集成开发环境,适用于C++编程,支持多种平台,包括Linux。我们将主要关注以下几个关键知识...

    C/S B/S 素材

    C/S架构的优势在于交互性强,用户体验良好,但缺点是需要为每个客户端单独安装和维护软件,更新迭代成本较高。 B/S架构,又称为浏览器-服务器架构,是基于Web的多层架构。用户只需通过浏览器访问服务器上的Web应用...

    C/S与B/S并用的高校教务管理系统研究与设计

    ### C/S与B/S并用的高校教务管理系统研究与设计 #### 一、引言 随着信息技术的快速发展,特别是互联网技术的普及,各种计算模式也在不断地演变和发展。其中,客户端/服务器(Client/Server,简称C/S)模式与浏览器/...

    C/S技术HTML中JAVASCRIPT的高级运用

    在IT行业中,C/S(Client/Server)架构是一种常见的软件设计模式,它将应用程序的用户界面部分和数据处理部分分离,使得客户端可以提供交互式的用户体验,而服务器端负责处理复杂的业务逻辑和数据管理。HTML...

    B/S框架和C/S框架的区别

    ### B/S与C/S框架的区别 #### 一、概述 在信息技术领域中,B/S(Browser/Server,浏览器/服务器)架构与C/S(Client/Server,客户端/服务器)架构是两种非常重要的软件系统设计模式。这两种模式在实际应用中各有...

    B/S架构的原理与应用

    - **安全性对比**:C/S架构下,由于客户端和服务器之间直接通信,每一台客户端都可能成为安全隐患,尤其是在网络环境中;而B/S架构中,所有数据处理都在服务器端完成,客户端只负责展示和用户交互,从而在一定程度上...

Global site tag (gtag.js) - Google Analytics