Java | Set 1中的多线程聊天应用程序(服务器端编程)

先决条件: 在socket编程中引入线程 在上面的文章中,创建了一个简单的日期时间服务器,它使用线程同时处理多个用户请求。它解释了网络编程中线程的基本概念。同样的概念也可以使用,只需稍加修改即可扩展上述想法,并创建一个类似于facebook messenger、whatsapp等的聊天应用程序。 下面的文章将详细介绍这种应用程序的实现、限制及其解决方案。 在这一集中,我们将讨论服务器端编程(Server.java),在中讨论客户端编程(Client.java) 第二组 .

null

服务器端编程(Server.java)

1.服务器类: 主服务器实现很简单,与前一篇文章类似。以下几点有助于理解服务器实现:

  1. 服务器运行一个无限循环来不断接受传入的请求。
  2. 当请求到来时,它会分配一个新线程来处理通信部分。
  3. 服务器还将客户机名称存储到一个向量中,以跟踪连接的设备。向量存储与当前请求对应的线程对象。helper类使用这个 矢量 查找要向其发送邮件的收件人的姓名。由于这个向量包含所有流,handler类可以使用它成功地将消息传递给特定的客户端。
  4. 调用 开始() 方法

2.ClientHandler类: 与前一篇文章类似,我们创建了一个helper类来处理各种请求。这一次,除了套接字和流之外,我们还引入了一个name变量。这将保存连接到服务器的客户端的名称。以下几点有助于理解ClientHandler的实现:

  • 每当处理程序收到任何字符串时,它都会将其拆分为消息和收件人部分。为此,它使用Stringtokenizer,并将“#”作为分隔符。这里假设字符串的格式始终为:
message # recipient
  • 然后,它会在“已连接的客户端”列表中搜索收件人的姓名,并将其作为向量存储在服务器中。如果它在客户机列表中找到收件人名称,它将在其输出流中转发消息,并在消息前面加上发件人的名称。

JAVA

// Java implementation of  Server side
// It contains two classes : Server and ClientHandler
// Save file as Server.java
import java.io.*;
import java.util.*;
import java.net.*;
// Server class
public class Server
{
// Vector to store active clients
static Vector<ClientHandler> ar = new Vector<>();
// counter for clients
static int i = 0 ;
public static void main(String[] args) throws IOException
{
// server is listening on port 1234
ServerSocket ss = new ServerSocket( 1234 );
Socket s;
// running infinite loop for getting
// client request
while ( true )
{
// Accept the incoming request
s = ss.accept();
System.out.println( "New client request received : " + s);
// obtain input and output streams
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
System.out.println( "Creating a new handler for this client..." );
// Create a new handler object for handling this request.
ClientHandler mtch = new ClientHandler(s, "client " + i, dis, dos);
// Create a new Thread with this object.
Thread t = new Thread(mtch);
System.out.println( "Adding this client to active client list" );
// add this client to active clients list
ar.add(mtch);
// start the thread.
t.start();
// increment i for new client.
// i is used for naming only, and can be replaced
// by any naming scheme
i++;
}
}
}
// ClientHandler class
class ClientHandler implements Runnable
{
Scanner scn = new Scanner(System.in);
private String name;
final DataInputStream dis;
final DataOutputStream dos;
Socket s;
boolean isloggedin;
// constructor
public ClientHandler(Socket s, String name,
DataInputStream dis, DataOutputStream dos) {
this .dis = dis;
this .dos = dos;
this .name = name;
this .s = s;
this .isloggedin= true ;
}
@Override
public void run() {
String received;
while ( true )
{
try
{
// receive the string
received = dis.readUTF();
System.out.println(received);
if (received.equals( "logout" )){
this .isloggedin= false ;
this .s.close();
break ;
}
// break the string into message and recipient part
StringTokenizer st = new StringTokenizer(received, "#" );
String MsgToSend = st.nextToken();
String recipient = st.nextToken();
// search for the recipient in the connected devices list.
// ar is the vector storing client of active users
for (ClientHandler mc : Server.ar)
{
// if the recipient is found, write on its
// output stream
if (mc.name.equals(recipient) && mc.isloggedin== true )
{
mc.dos.writeUTF( this .name+ " : " +MsgToSend);
break ;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
try
{
// closing resources
this .dis.close();
this .dos.close();
} catch (IOException e){
e.printStackTrace();
}
}
}


输出:

New client request received : Socket[addr=/127.0.0.1,port=61818,localport=1234]Creating a new handler for this client...Adding this client to active client listNew client request received : Socket[addr=/127.0.0.1,port=61819,localport=1234]Creating a new handler for this client...Adding this client to active client list

限制: 虽然上面的服务器实现能够处理大多数场景,但上面定义的方法存在一些缺点。

  • 从上述项目中可以清楚地看到: 如果客户端数量增加,搜索时间就会增加 在handler类中。为了避免这种增加,可以使用两个哈希映射。以名称为键,以活动列表中的索引为值。另一个是索引作为键,关联的处理程序对象作为值。通过这种方式,我们可以快速查找两个哈希映射以匹配收件人。让读者来实现这个黑客,以提高实现的效率。
  • 另一件需要注意的事情是,这个实现 当用户断开与服务器的连接时无法正常工作 。由于在此实现中未处理断开连接,因此会引发很多错误。它可以像前面的基本TCP示例一样轻松实现。它也留给读者在程序中实现此功能。

客户机程序(client.java)与之前的文章有很大的不同,因此将在本系列的第2集中讨论。

相关文章: 多线程聊天应用程序|集2

本文由 Rishabh Mahrsee .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄去评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享