您的位置:首页 > 编程语言 > Java开发

java socket实现聊天室 java实现多人聊天功能

2018-07-22 12:26 911 查看

用java socket做一个聊天室,实现多人聊天的功能。看了极客学院的视频后跟着敲的。(1DAY)

服务端:

1. 先写服务端的类MyServerSocket,里面放一个监听线程,一启动就好
2. 实现服务端监听类ServerListener.java,用accept来监听,一旦有客户端连上,生成新的socket,就新建个线程实例ChatSocket。启动线程后就把线程交给ChatManager管理
3. 在ChatSocket中实现从客户端读取内容,把读取到的内容发给集合内所有的客户端
4. ChatManager里面用vector来管理socket线程实例ChatSocket,并实现发送信息给其他的客户端

客户端:

1. 新建一个继承JFrame的MainWindow.java类,主要实现聊天窗口的UI,以及事件响应。
2. 新建StartClient.java类,把MainWindow中生成MainWindow主方法部分代码拷贝过来,这样就能在主程序中把窗体执行出来了。
3. 新建ChatManager(需要单例化的类)管理socket,实现聊天的输入输出功能。最后记得在1中新建窗口后,传一份frame的引用到ChatManager中,才能实现ChatManager对界面的显示。

工程结构如图

以下为代码

服务端:

1. 先写服务端的类MyServerSocket,里面放一个监听线程,一启动就好

package com.starnet.testserversocket.main;
public class MyServerSocket {
public static void main(String[] args) {
new ServerListener().start();
}
}

2.实现服务端监听类ServerListener.java,用accept来监听,一旦有客户端连上,生成新的socket,就新建个线程实例ChatSocket。启动线程后就把线程交给ChatManager管理

package com.starnet.testserversocket.main;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JOptionPane;
public class ServerListener extends Thread {
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(23456);
while (true) {
// block
Socket socket = serverSocket.accept();
// 建立链接
JOptionPane.showMessageDialog(null, "有客户端连到本机23456端口");
//将socket传递给新的线程
ChatSocket cs= new ChatSocket(socket);
cs.start();
ChatManager.getChatManager().add(cs);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

3.在ChatSocket中实现从客户端读取内容,把读取到的内容发给集合内所有的客户端

package com.starnet.testserversocket.main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
/*每一个连上的客户端,服务器都有一个线程为之服务*/
public class ChatSocket extends Thread {
Socket socket;
public ChatSocket(Socket s) {
this.socket = s;
}
//发送数据
public void out(String out) {
try {
socket.getOutputStream().write(out.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//服务器会不断地从客户端读取内容,把读取到的内容发给集合内所有的客户端。
public void run() {
try {
//接收数据
BufferedReader br = new BufferedReader(
new InputStreamReader(
socket.getInputStream(), "UTF-8"));
String line=null;
//发送读到的内容
while ((line = br.readLine())!=null) {
System.out.println(line);
ChatManager.getChatManager().publish(this, line);
}
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

4.ChatManager里面用vector来管理socket线程实例ChatSocket,并实现发送信息给其他的客户端

package com.starnet.testserversocket.main;
import java.util.Vector;
//一个聊天服务器只能有一个manager,要单例化处理
public class ChatManager {
private ChatManager(){}
private static final ChatManager CM=new ChatManager();
public static ChatManager getChatManager(){
return CM;
}
Vector<ChatSocket> vector = new Vector<ChatSocket>();
/*增加ChatSocket 实例到vector中*/
public void add(ChatSocket cs){
vector.add(cs);
}
/*发布消息给其他客户端
*ChatSocket cs: 调用publish的线程
*msg:要发送的信息 */
public void publish(ChatSocket cs, String msg){
for (int i = 0; i < vector.size(); i++) {
ChatSocket csTemp = vector.get(i);
if (!cs.equals(csTemp)) {
csTemp.out(msg+"\n");//不用发送给自己。
}
}
}
}

客户端:

1. 新建一个继承JFrame的MainWindow.java类,主要实现聊天窗口的UI,以及事件响应。

package com.starnet.javaclient.view;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextArea;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.LayoutStyle.ComponentPlacement;
import com.starnet.javaclient.main.ChatManager;
import com.sun.xml.internal.ws.client.SenderException;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class MainWindow extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private JTextArea txt;
private JTextField txtip;
private JTextField txtSend;
/**
* Create the frame.
*/
public MainWindow() {
setAlwaysOnTop(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
txt = new JTextArea();
txt.setText("ready...");
txtip = new JTextField();
txtip.setText("127.0.0.1");
txtip.setColumns(10);
JButton btnConnect = new JButton("connect");
btnConnect.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
ChatManager.getChatManager().connect(txtip.getText());
}
});
txtSend = new JTextField();
txtSend.setText("hello");
txtSend.setColumns(10);
JButton btnSend = new JButton("send");
btnSend.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
ChatManager.getChatManager().send(txtSend.getText());
appendText("我说: "+txtSend.getText());
txtSend.setText("");
}
});
GroupLayout gl_contentPane = new GroupLayout(contentPane);
gl_contentPane.setHorizontalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(Alignment.TRAILING, gl_contentPane.createSequentialGroup()
.addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING)
.addGroup(gl_contentPane.createSequentialGroup()
.addComponent(txtSend, GroupLayout.DEFAULT_SIZE, 325, Short.MAX_VALUE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(btnSend, GroupLayout.PREFERRED_SIZE, 109, GroupLayout.PREFERRED_SIZE))
.addGroup(Alignment.LEADING, gl_contentPane.createSequentialGroup()
.addComponent(txtip, GroupLayout.PREFERRED_SIZE, 294, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(btnConnect, GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE))
.addComponent(txt, GroupLayout.DEFAULT_SIZE, 434, Short.MAX_VALUE))
.addContainerGap())
);
gl_contentPane.setVerticalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addGroup(gl_contentPane.createParallelGroup(Alignment.BASELINE)
.addComponent(txtip, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(btnConnect))
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(txt, GroupLayout.DEFAULT_SIZE, 198, Short.MAX_VALUE)
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING)
.addComponent(btnSend)
.addComponent(txtSend, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)))
);
contentPane.setLayout(gl_contentPane);
}
/*客户端发送的内容添加到中间的txt控件中*/
public void appendText(String in) {
txt.append("\n" + in);
}
}

2.新建StartClient.java类,把MainWindow中生成MainWindow主方法部分代码拷贝过来,这样就能在主程序中把窗体执行出来了。

package com.starnet.javaclient.main;
import java.awt.EventQueue;
import com.starnet.javaclient.view.MainWindow;
public class StartClient {
public static void main(String[] args) {
/*先新建一个jframe,然后把自动生成的代码贴过来*/
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainWindow frame = new MainWindow();
frame.setVisible(true);
//创建完这个frame以后,传一份window的引用到ChatManager去
ChatManager.getChatManager().setWindow(frame);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}

3.新建ChatManager(需要单例化的类)管理socket,实现聊天的输入输出功能。最后记得在1中新建窗口后,传一份frame的引用到ChatManager中,才能实现ChatManager对界面的显示。

package com.starnet.javaclient.main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import com.starnet.javaclient.view.MainWindow;
public class ChatManager {
private ChatManager(){}
private static final ChatManager instance=new ChatManager();
public static ChatManager getChatManager(){
return instance;
}
MainWindow window;//为了能在界面上显示服务器发来的信息,就需要传一个MainWindow的引用进来
Socket socket;
private String IP;
BufferedReader bReader;
PrintWriter pWriter;
public void setWindow(MainWindow window) {
this.window = window;
window.appendText("文本框已经和chatManager绑定了");
}
public void connect(String ip) {
this.IP = ip;
new Thread(){
@Override
public void run() {
//实现网络方法
try {
socket = new Socket(IP, 23456);
//输出流
pWriter = new PrintWriter(
new OutputStreamWriter(
socket.getOutputStream()));
//输入流
bReader = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
String line = null;
//如果读取数据为空
while ((line = bReader.readLine())!=null) {
window.appendText("收到: "+line);
}
//读完数据之后要关闭
pWriter.close();
bReader.close();
pWriter = null;
bReader = null;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
public void send(String sendMsg){
if (pWriter!=null) {
pWriter.write(sendMsg+"\n");
pWriter.flush();
} else {
window.appendText("当前链接已经中断...");
}
}
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java socket 聊天室
相关文章推荐