服务器的根本创建方法是 创建一个ServerSocket的对象,让对象在某个端口上监听。
调用accept方法阻塞端口,如果有客户机连接上了服务器的该端口,然后启动一个新的socket与该客户机进行通信。
如果把通信的处理方法放在一个线程类里面,就可以实现多人同时访问,即多线程处理。
服务器的多线程处理类(多人聊天室)
从宏观上来看,服务器主要是做两件事情:
1、从客户端得到输入的内容;
2、将输入的内容接收后写到其他的客户端。
从这里就可以明白,服务器处理方法所需要的方法或者属性变量如下:
需要一个存放连接对象的列表,并提供对列表中连接对象的增加和删除操作。(存放线程列表,里面的线程是用来操作连接对象socket的)
需要一个获取客户端输入的方法,该方法通过客户端的readLine方法返回一个字符串,然后服务器将以流的形式,写到每一个客户端中
需要一个将某个客户端发过来的消息转发全部客户端的一个方法。遍历每个元素,然后写给客户端。
处理类的本质其实是一个实现了多线程功能的 socket对象的包装类,在这个包装类中,所有的socket对象都可以从中获取到读写流对象,并且有读写方法,这样以来,服务器就不要担心如何去处理每个连接,它要做的只是将每个请求回应,然后将请求转交给处理类,即线程去处理。
其实可以说整个服务器的处理核心就是这个处理类,这个类的处理流程如下:
当创建了一个连接socket对象的线程之后,就将这个线程对象放入列表当中去,列表是静态的,所以可以让各个线程同时访问,或者说可以让各个线程共享这个变量。
之后就是将欢迎辞,发到各个线程所对应的socket对象,因为每个对象都在处理类中被包装了,所有的对象都有自己的读写流,则可以在每个单独的线程中去写信息。实现聊天室的效果。线程一直在等待读取客户端输入的数据,只要有输入,就会马上将数据反应到每个客户端上来。
如果输入某个字符,比如说“bye”就让其自动退出,将该线程多对应的连接对象close,将列表中该线程移除。
总体来说,服务器端的开发流程和要注意的地方已经介绍完了,最重要的一点就是,服务器其实只是在等待,处理线程类才是最终的“劳动者”。了解和熟悉服务器的工作流程对以后客户端课服务器的同时开发有着不可或缺的作用。
服务器启动程序 写道
package cn.netjava.C_S.v3;
import java.net.ServerSocket;
public class ChatServerV3 {
//程序入口
public static void main(String[] args) {
ChatServerV3 ms=new ChatServerV3();
int port =9999;
ms.setUpServer(port);
}
//在指定端口上启动服务器
public void setUpServer(int port){
try{
ServerSocket sc=new ServerSocket(port);//在指定端口上构造一个服务器对象
new ChatTools().serverUI();
ChatTools.information.setText("简单聊天服务器创建成功,等待在端口: "+port+"\n");
while(true){//让服务器进入循环监听状态
java.net.Socket client=sc.accept();
ChatThread ct=new ChatThread(client);
ct.start();//启动一个线程,去处理这个客户机的连结对象
}
}catch(Exception ef){
ef.printStackTrace();
}
}
}
package cn.netjava.C_S.v3;
import java.awt.Color;
import java.awt.FlowLayout;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
public class ChatTools {
//服务器显示框
static JTextArea information =new JTextArea(" ");
static JLabel count= new JLabel();
static long history=0;
//服务器内部用以保存所有客户线程对象的列表对象
static List<ChatThread> clientList=new ArrayList<ChatThread>();
//1.根据用户名,密码认证用户的方法,如果认证通过,返回true;
public static boolean authUser(String userName,String pwd){
//返加Map中是否有这个用户名做key,这就要求用户名必须是唯一的
return userInfoMap.containsKey(userName);
}
//2.将一个连上来并通过认证的的客户机对象加入到队列中
public static void addClient2Queue(ChatThread ct){
clientList.add(ct);
history++;
}
//3.从队列中移除 用户名所代表的客户机对象
public static void removeClient(String userName){
for(int i=0;i<clientList.size();i++){
ChatThread cs=clientList.get(i);
if(cs.getUserName().equals(userName)){
clientList.remove(i);
}
}
}
//4.调用后,将userName用户发的消息发给所有客户机
public static void castMsg(String userName,String msg){
for(int i=0;i<clientList.size();i++){
ChatThread cs=clientList.get(i);
cs.sendMsg2Me(userName+"说:"+msg+"\n");
}
}
//服务器端用以保存用户名,密码的列表,表中的键为用户名,值为密码
private static Map<String,String> userInfoMap=new HashMap<String,String>();
//静态块:用做在系统初始时,初始化表户信息表中的用户名和密码,此处模拟生成数据
static {
for(int i=0;i<10;i++){
String key="user"+i;
String value="pwd";
userInfoMap.put(key,value);
javax.swing.SwingUtilities.updateComponentTreeUI(ChatTools.information);
}
}
public JFrame serverUI(){
JFrame serverFrame= new JFrame("多人聊天室服务器监控端");
count.setSize(800, 20);
serverFrame.setSize(800,600);
serverFrame.setDefaultCloseOperation(3);
serverFrame.setLayout(new FlowLayout());
information= new JTextArea(30,60);
information.setEditable(false);
information.setBackground(Color.decode("#33CCCC"));
information.setWrapStyleWord(true);
serverFrame.add(count);
serverFrame.add(information);
serverFrame.setVisible(true);
return serverFrame;
}
}
package cn.netjava.C_S.v3;
import java.text.DateFormat;
import java.util.Date;
public class DateProcess {
public String process(){
DateFormat df = new java.text.SimpleDateFormat("yyyy年MM月dd日-hh:mm:ss");
return df.format(new Date());
}
}
package cn.netjava.C_S.v3;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class ChatThread extends Thread{
//构造这个线程对象时,传客户机连结对象,在线程中处理.
public ChatThread(Socket client){
this.client=client;
}
public void run(){
processClient(this.client);//调用处理客户端的方法
}
//对外提供的调用接口,将消息发送给我代表的客户端
public void sendMsg2Me(String msg){
try{
ous.write((msg+"\r\n").getBytes());
ous.flush();//将消息发送到客户机
}catch(Exception ef){}
}
// 处理客户机连结对象socket
private void processClient(java.net.Socket client){
try{
InputStream ins= client.getInputStream();
ous= client.getOutputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(ins));
//1.验证用户名和密码是否合格,如果不合格,则关闭连结,方法执行在此中断
String msg = "请输入用户名:";
sendMsg2Me(msg);
BufferedReader breader=new BufferedReader(new InputStreamReader(ins));
userName=breader.readLine();//读取用户输入的用户名,这个对象的userName属性赋上了值
msg="请输入你的密码:";
sendMsg2Me(msg);
String pwd=br.readLine();//读取用户输入的密码
//1.验证用户名和密码是否合格,如果不合格,则关闭连结,方法执行在此中断
if(!ChatTools.authUser(userName, pwd)){
msg="用户名或密码错!请询问管理员";
sendMsg2Me(msg);
client.close();
return ;
}
ChatTools.addClient2Queue(this); //2.将这个线程对象放入服务器列表
String input="";
ChatTools.castMsg(userName,"我来啦!(已经加入本聊天室)");
ChatTools.count.setText("当前在线客户端: "+ChatTools.clientList.size()+" ,总共有 "+ChatTools.history +"个客户端连接过本服务器");
String temp = ChatTools.information.getText();
String time = (new DateProcess().process());
ChatTools.information.setText(temp+time+"------"+userName+" 已经与服务器建立连接...IP地址: "
+client.getRemoteSocketAddress()+"\n");
javax.swing.SwingUtilities.updateComponentTreeUI(ChatTools.information);
//如果客户机发送 bye ,退出客户机
while(!input.equalsIgnoreCase("bye")){
input=br.readLine();//循环读取客户机的输入
ChatTools.castMsg(userName,input);//3.将读到的这条消息发送给客户机:
}
client.close();
}catch(Exception ef){
ef.printStackTrace();
}
ChatTools.castMsg(userName,"我走了!(已经退出本聊天室)");
String temp = ChatTools.information.getText();
String time = (new DateProcess().process());
ChatTools.information.setText(temp+time+"------"+userName+" 已经与服务器断开连接...IP地址: "
+client.getRemoteSocketAddress()+"\n");
javax.swing.SwingUtilities.updateComponentTreeUI(ChatTools.information);
ChatTools.removeClient(userName);//4.至此,这个客户机己退出,将其从列表中移除,
ChatTools.count.setText("当前在线客户端: "+ChatTools.clientList.size()+" ,总共有 "+ChatTools.history +"个客户端连接过本服务器");
}
//得到这个处理线程对象所代表客户机的用户名字
public String getUserName(){
return this.userName;
}
private String userName;//客户机名字,要在类中其它方法中调用,所以设置为属性
private OutputStream ous;//输出流对象,要在类中其它方法中调用,所以设置为属性
private Socket client;//客户机连结对象
public Socket getClient() {
return client;
}
}
分享到:
相关推荐
《Java程序设计实训》报告的主题是构建一个多人聊天室,旨在通过这个项目加深对Java语言的理解,特别是Java的多线程、GUI编程以及Socket网络编程技术。以下是对这些知识点的详细说明: 1. **Java语言**:Java是一种...
在这个多人聊天室项目中,服务器端使用ServerSocket监听特定端口,等待客户端的连接请求;客户端则通过Socket与服务器建立连接,进行数据的收发。 其次,IO(Input/Output)是Java处理输入输出的关键技术。在聊天室...
该课程设计项目主要关注的是在Linux环境下构建一个嵌入式系统的多人聊天室应用。这个项目不仅涉及到了软件开发,还涵盖了操作系统和网络通信的基础知识,是计算机科学与技术专业学生在学习过程中的一项重要实践。 ...
Java是一种广泛应用于服务器端开发的高级编程语言,具有跨平台性、稳定性和高效性,非常适合构建网络应用,如聊天室。 【源码结构与知识点】: 1. **网络编程基础**:在Java中,主要使用`java.net.Socket`和`java...
总结,这个项目展示了如何利用Java WebSocket API构建一个实时的多人聊天室,对于学习WebSocket协议、Java网络编程以及实时应用的开发具有很高的参考价值。通过阅读和理解源代码,开发者可以掌握WebSocket的使用技巧...
在【描述】中提到,“聊天室服务器聊天室服务器客户端”,这表明该聊天室项目包含了两个关键组件:服务器端和客户端。服务器端负责接收和广播用户的聊天信息,而客户端则是用户进行交流的界面。这两个组件通常通过...
这个“简单的多人聊天室”项目包含两个主要组件:`chatClient`和`chatServer`,分别代表客户端和服务器端。 客户端(chatClient)是用户与聊天室交互的部分,通常包括一个用户界面,让用户输入消息并显示来自其他...
在多人聊天室中,服务器端需要监听特定的端口,等待来自多个客户端的连接请求。当接收到数据后,服务器会解析消息并广播给所有在线的用户。同时,每个客户端也会创建自己的Socket连接,用于向服务器发送聊天消息。 ...
基于Linux操作系统C语言开发的多人聊天室程序设计与实现 本文档主要介绍了基于Linux操作系统使用C语言开发的多人聊天室程序的设计与实现。该项目的设计目的是为了开发一个功能完备的聊天室程序,提供多人实时聊天的...
【标题】中的“大学生计算机网络课程期末作业java聊天系统(多人聊天室)原创”表明这是一个由大学生完成的项目,作为其计算机网络课程的期末作业。这个项目是一个基于Java编程语言实现的聊天系统,具备多人聊天的...
在本项目中,我们讨论的是一个使用Java编程语言开发的简易多人聊天室。这个聊天室主要是为了解决作业中的问题,尽管它存在一些已知的缺陷,但它仍然是一个很好的起点来学习和理解Java多线程以及网络编程的基本概念。...
1. 用Java图形用户界面编写聊天室服务器端和客户端, 支持多个客户端连接到一个服务器。每个客户端能够输入账号。 2. 可以实现群聊(聊天记录显示在所有客户端界面)。 3. 完成好友列表在各个客户端上显示。 4. 可以...
【Java 多人聊天室可私聊】是一个基于Java编程语言开发的实时通讯软件,它具备图形用户界面(GUI)并模拟了QQ等流行聊天应用的功能。这个项目的核心知识点包括Java编程、网络通信、多线程、GUI设计以及数据交换格式...
Java Swing 多人聊天室是一个基于Java编程语言的桌面应用程序,设计用于实现多个用户之间的实时通信。这个系统利用了Swing库来构建图形用户界面(GUI),提供了丰富的组件和功能,使得用户可以方便地进行文字聊天。...
1. **服务器端开发** - **Socket编程**:在Linux环境下,实现网络通信的基础是socket接口。服务器端需要监听特定的端口,等待客户端的连接请求。一旦有新的连接,服务器就会创建一个新的socket与之通信。 - **多...
【Java多人聊天室源代码】是一个基于Java编程语言实现的多用户实时通信系统,它允许多个用户在同一时间进行在线对话。这个系统的核心是利用网络编程技术实现数据的发送与接收,使得聊天室中的用户可以即时交换消息。...
Unity是一款强大的跨平台游戏开发引擎,它...综上所述,"Unity手机android端多人聊天室demo"涵盖了Unity开发、网络编程、多平台兼容性、实时通信和用户体验等多个方面的知识,是一个全面展示Unity综合能力的项目实例。
【Java简单多人聊天室】是一个基于Java编程语言的多用户实时交流系统,它利用了Java的多线程特性,使得多个用户可以同时进行聊天。这个项目对于初学者来说是一个很好的学习资源,因为它可以帮助理解Java的基础知识,...
Python实现的多人聊天室源码+实验报告(高分期末大作业)需求(开发主题,目的) 社交是当下时代人们每天必不可少的一件事情,随着网络的发展,互联网社交成为了一个 的发展趋势,此时,就需要一个能实现社交功能的...