实践周的一个小项目:多人聊天室(TCP、多线程、Socket、私聊、广播、多用户)
前言
这个聊天室使用eclipse开发,基于JAVA-SWT开发GUI
提示:以下是本篇文章正文内容,下面案例可供参考
Server
预览
详细流程图
代码
代码如下(示例):
package TCP.Server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class MiniServer {
protected Shell shell;
private Text text_Port;
private Text text_message;
private List list;
private Button btnStart ;
private Label lblNewLabel_2;
private String ip="127.0.0.1";
static Map<String ,Socket> map=new HashMap<String ,Socket>();
static ArrayList<Users > UsersList=new ArrayList<>();
public int ServerPort=4321;
private boolean ButtonMark=false;
private final String MessageSplit = "###";
public static void main(String[] args) {
try {
MiniServer window = new MiniServer();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
public void open() {
Display display = Display.getDefault();
createContents();
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
protected void createContents() {
shell = new Shell();
shell.setSize(486, 300);
shell.setText("MiniChatServer");
shell.addShellListener(new ShellAdapter() {
public void shellClosed(ShellEvent e) {
DisConnect();
System.exit(0);
}});
text_Port = new Text(shell, SWT.BORDER);
text_Port.setText(ServerPort+"");
text_Port.setBounds(215, 19, 94, 23);
btnStart = new Button(shell, SWT.NONE);
btnStart.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ServerStart start=null;
if(!ButtonMark)
{
btnStart.setText("Stop");
ButtonMark=!ButtonMark;
start=new ServerStart();
start.start();
}
else {
btnStart.setText("Start!!!");
ButtonMark=!ButtonMark;
DisConnect();
text_message.append("服务已关闭\n");
}
}
});
btnStart.setBounds(351, 10, 109, 41);
btnStart.setText("Start!!!");
text_message = new Text(shell, SWT.BORDER | SWT.V_SCROLL);
text_message.setBounds(10, 74, 299, 176);
list = new List(shell, SWT.MULTI | SWT.BORDER);
list.setItems(new String[] {"Server"});
list.setBounds(351, 73, 109, 176);
Label lblNewLabel = new Label(shell, SWT.NONE);
lblNewLabel.setBounds(171, 22, 30, 17);
lblNewLabel.setText("\u7AEF\u53E3");
Label lblNewLabel_1 = new Label(shell, SWT.NONE);
lblNewLabel_1.setBounds(10, 22, 40, 17);
lblNewLabel_1.setText("\u672C\u673Aip");
lblNewLabel_2 = new Label(shell, SWT.BORDER | SWT.WRAP);
lblNewLabel_2.setBounds(56, 21, 117, 21);
lblNewLabel_2.setText(getHostAddress());
}
public void BroadSendMessage(String message)
{
DataOutputStream out;
for (Map.Entry<String , Socket> entry : map.entrySet()) {
try {
out=new DataOutputStream(entry.getValue().getOutputStream());
out.writeUTF("Broad"+MessageSplit+message);
AppendMessage("已发送"+entry.getKey());
} catch (IOException e) {
}
}
}
public void SendMessage(String name,String message) {
DataOutputStream out;
for (Map.Entry<String , Socket> entry : map.entrySet()) {
if(entry.getKey().equals(name))
{
try {
out=new DataOutputStream(entry.getValue().getOutputStream());
out.writeUTF("PrivateChat"+MessageSplit+message);
AppendMessage("已发送私聊"+entry.getKey());
} catch (IOException e) {
}
return;
}
}
}
public void SendList()
{
AppendMessage("准备发送list");
String message=new String("Server"+MessageSplit);
for (Map.Entry<String , Socket> entry : map.entrySet()) {
message+=entry.getKey()+MessageSplit;
}
AppendMessage("发送"+message);
for (Map.Entry<String , Socket> entry : map.entrySet()) {
try {
DataOutputStream out=new DataOutputStream(entry.getValue().getOutputStream());
out.writeUTF(message);
} catch (IOException e) {
}
}
}
public void AppendListItems(String Items) {
Display.getDefault().syncExec(new Runnable() {
public void run() {
list.add(Items);
}
});
}
public void AppendMessage(String Message) {
Display.getDefault().syncExec(new Runnable() {
public void run() {
text_message.append(Message + '\n');
}
});
}
public void SetListItems(String [] List) {
Display.getDefault().syncExec(new Runnable() {
public void run() {
list.setItems(List);
}
});
}
public void SetListItems() {
Display.getDefault().syncExec(new Runnable() {
public void run() {
list.setItems(new String[] {"Server"});
for (Map.Entry<String , Socket> entry : map.entrySet()) {
list.add(entry.getKey());
}
}
});
}
public boolean AgreeConnect(String name) {
if (map.containsKey(name)) {
return false;
}
return true;
}
public void DisConnect(String name)
{
try {
map.get(name).close();
} catch (IOException e) {
}finally {
for (int i = 0; i < UsersList.size(); i++) {
if(UsersList.get(i).UserName.equals(name))
{
UsersList.remove(i);
break;
}
}
map.remove(name);
SetListItems();
SendList();
}
}
public void DisConnect() {
SetListItems(new String [] {"Server"});
for (Map.Entry<String , Socket> entry : map.entrySet()) {
try {
DataOutputStream out=new DataOutputStream(entry.getValue().getOutputStream());
out.writeUTF("DisConnect"+MessageSplit);
} catch (IOException e) {
}
}
for (Users users : UsersList) {
try {
users.socket.close();
} catch (IOException e) {
}
users.stop();
}
map.clear();
UsersList.clear();
}
String getHostAddress()
{
InetAddress addr;
try {
addr = InetAddress.getLocalHost();
return addr.getHostAddress();
} catch (UnknownHostException e) {
return "127.0.0.1";
}
}
class ServerStart extends Thread{
@Override
public void run() {
while (true) {
try {
ServerSocket server=new ServerSocket(ServerPort);
AppendMessage("已开启server,等待连接??");
Socket socket=server.accept();
new Users(socket).start();
} catch (IOException e) {
}
}
}
}
class Users extends Thread{
DataInputStream in;
DataOutputStream out;
String UserName=null;
Socket socket;
Users(Socket socket){
if(!ButtonMark)
return;
try {
this.socket=socket;
in=new DataInputStream(socket.getInputStream());
out=new DataOutputStream(socket.getOutputStream());
UserName=in.readUTF();
if(UserName!=null&&AgreeConnect(UserName))
{
out.writeUTF("agree");
map.put(this.UserName, this.socket);
UsersList.add(this);
SendList();
AppendListItems(UserName);
AppendMessage(UserName+"已连接");
}
else {
out.writeUTF("Disagree");
out.writeUTF(UserName+"已登录");
}
} catch (IOException e) {
}
}
@Override
public void run() {
while (true) {
try {
if(!ButtonMark)
{
in.close();
this.socket.close();
this.stop();
}
String ClientMessage=in.readUTF();
AppendMessage("已接收"+ClientMessage);
String[] message=ClientMessage.split(MessageSplit);
InformationCenter(message);
} catch (IOException e) {
}
}
}
public void InformationCenter(String[] message)
{
switch (message[0]) {
case "Connect":
try {
out.writeUTF("agree");
AppendMessage("已同意"+UserName+"连接请求");
} catch (IOException e) {
}
break;
case "UpdateList":
SendList();
AppendMessage("已发送"+UserName+"的List");
break;
case "Broad":
BroadSendMessage(message[1]);
AppendMessage("广播"+message[1]);
break;
case "DisConnect":{
DisConnect(message[1]);
AppendMessage(UserName+"已断线");
this.stop();
break;
}
default://私聊
SendMessage(message[0], message[1]);
break;
}
}
}
}
Client
预览
详细流程图
代码
package TCP.Client;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import javax.swing.JOptionPane;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.wb.swt.SWTResourceManager;
public class MiniClient {
protected Shell shell;
private Text text_Port;
private Text text_IP;
private Text text_Input;
private Text text_Message;
private List UserList;
Button btnConnect;
private boolean ButtonMark = false;
private String IP = "127.0.0.1";
private String UserName = null;
private int Port = 4321;
private Text text_Name;
private final String MessageSplit = "###";
private String PrivateObject = "Broad";
private Socket socket=null;
private Read read;
public static void main(String[] args) {
try {
MiniClient window = new MiniClient();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
public void open() {
Display display = Display.getDefault();
createContents();
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
protected void createContents() {
shell = new Shell();
shell.setSize(560, 448);
shell.setText("MiniChat");
shell.addShellListener(new ShellAdapter() {
public void shellClosed(ShellEvent e) {
DisConnect(socket, read);
System.exit(0);
}});
text_Name = new Text(shell, SWT.BORDER);
text_Name.setBounds(337, 22, 72, 23);
btnConnect = new Button(shell, SWT.NONE);
btnConnect.setFont(SWTResourceManager.getFont("微软雅黑", 10, SWT.NORMAL));
btnConnect.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (text_Name.getText().equals("")) {
JOptionPane.showMessageDialog(null, "必须设置用户名", "提示", JOptionPane.INFORMATION_MESSAGE);
} else {
if (!ButtonMark) {
SwitchButton();
Initialization();
} else {
SwitchButton();
DisConnect(socket,read);
}
}
}
});
btnConnect.setBounds(434, 10, 100, 47);
btnConnect.setText("Connect!!!");
text_Port = new Text(shell, SWT.BORDER);
text_Port.setText(this.Port + "");
text_Port.setBounds(194, 22, 72, 23);
text_IP = new Text(shell, SWT.BORDER);
text_IP.setText(this.IP);
text_IP.setBounds(33, 22, 115, 23);
Label lblIp = new Label(shell, SWT.NONE);
lblIp.setFont(SWTResourceManager.getFont("微软雅黑", 10, SWT.NORMAL));
lblIp.setBounds(10, 25, 17, 17);
lblIp.setText("IP");
Label lblPort = new Label(shell, SWT.NONE);
lblPort.setFont(SWTResourceManager.getFont("微软雅黑", 10, SWT.NORMAL));
lblPort.setBounds(154, 25, 34, 17);
lblPort.setText("Port");
text_Input = new Text(shell, SWT.BORDER);
text_Input.setFont(SWTResourceManager.getFont("微软雅黑", 13, SWT.NORMAL));
text_Input.setBounds(10, 332, 399, 61);
text_Input.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.keyCode == 13)
{
SendMessage();
text_Input.setText("");
}
}
});
Button btnSend = new Button(shell, SWT.NONE);
btnSend.setFont(SWTResourceManager.getFont("微软雅黑", 13, SWT.NORMAL));
btnSend.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
SendMessage();
}
});
btnSend.setBounds(434, 332, 100, 61);
btnSend.setText("Send");
text_Message = new Text(shell, SWT.BORDER | SWT.V_SCROLL);
text_Message.setFont(SWTResourceManager.getFont("微软雅黑", 13, SWT.NORMAL));
text_Message.setBounds(10, 60, 399, 266);
UserList = new List(shell, SWT.BORDER);
UserList.setFont(SWTResourceManager.getFont("微软雅黑", 13, SWT.NORMAL));
UserList.setBounds(434, 63, 100, 263);
UserList.addMouseListener(new MouseListener() {
public void mouseUp(MouseEvent arg0) {
PrivateObject=UserList.getSelection()[0];
}
public void mouseDown(MouseEvent arg0) {}
public void mouseDoubleClick(MouseEvent arg0) {}
});
Label lblName = new Label(shell, SWT.NONE);
lblName.setFont(SWTResourceManager.getFont("微软雅黑", 10, SWT.NORMAL));
lblName.setAlignment(SWT.CENTER);
lblName.setText("Name");
lblName.setBounds(272, 25, 59, 17);
}
void SwitchButton()
{
Display.getDefault().syncExec(new Runnable() {
public void run() {
if (!ButtonMark) {
btnConnect.setText("Disconnect");
ButtonMark = !ButtonMark;
} else {
btnConnect.setText("Connect!!!");
ButtonMark = !ButtonMark;
}
}
});
}
void Initialization() {
this.IP = this.text_IP.getText();
this.Port = Integer.parseInt(this.text_Port.getText());
this.UserName = this.text_Name.getText();
new Connect().start();
}
void ApplyUpdateList(Socket socket)
{
try {
DataInputStream in =new DataInputStream(socket.getInputStream());
UpdateList(in.readUTF());
} catch (IOException e) {
}
}
void AppendMessage(String Message) {
Display.getDefault().syncExec(new Runnable() {
public void run() {
text_Message.append(Message + '\n');
}
});
}
void SetListItems(String [] message)
{
Display.getDefault().syncExec(new Runnable() {
public void run() {
UserList.setItems(message);;
}
});
}
void UpdateList(String message) {
PrivateObject = "Broad";
try {
String[] Items = message.split(MessageSplit);
Items[0]="Broad";
SetListItems(Items);
} catch (Exception e) {
AppendMessage("更新列表失败");
}
}
void InformationCenter(String message,Socket socket) {
String[] split=message.split(MessageSplit);
switch (split[0]) {
case "Server": {
UpdateList(message);
break;
}
case "PrivateChat":{
AppendMessage("<私聊>\t"+split[1]);
break;
}
case "Broad":{
AppendMessage("<广播>\t"+split[1]);
break;
}
case "DisConnect":{
DisConnect(read);
break;
}
}
}
Boolean ApplyConnect(Socket socket) {
try {
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream());
out.writeUTF( UserName);
String ServerMessage = in.readUTF();
AppendMessage("向服务器发送连接请求");
if (ServerMessage.equals("agree")) {
AppendMessage("服务器同意连接请求");
return true;
} else {
AppendMessage("服务器不同意连接请求");
AppendMessage("原因:"+in.readUTF());
return false;
}
} catch (IOException e) {
SwitchButton();
AppendMessage("向服务器发送连接请求失败");
return false;
}
}
void DisConnect(Read read) {
AppendMessage("服务器要求断开连接");
SwitchButton();
SetListItems(new String[] {""});
PrivateObject = "Broad";
try {
read.socket.close();
} catch (IOException e) {
}
read.stop();
}
void DisConnect(Socket socket,Read read)
{
try {
SetListItems(new String[] {""});
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
String message = "DisConnect" + MessageSplit + UserName;
out.writeUTF(message);
AppendMessage("向服务器申请断开连接");
out.close();
} catch (IOException e) {
}
}
void SendMessage() {
if(socket!=null)
{
if(!text_Input.getText().equals(""))
{
if(!PrivateObject.equals("Broad"))
AppendMessage("<私聊>\t"+UserName + ":\t" + text_Input.getText());
String message = PrivateObject + MessageSplit + UserName + ":\t" + text_Input.getText();
DataOutputStream out;
try {
out = new DataOutputStream(socket.getOutputStream());
out.writeUTF(message);
} catch (IOException e) {
AppendMessage("发送消息失败");
}
}
else {
JOptionPane.showMessageDialog(null, "输入框为空", "提示", JOptionPane.INFORMATION_MESSAGE);
}
}
else {
JOptionPane.showMessageDialog(null, "未连接到服务器", "提示", JOptionPane.INFORMATION_MESSAGE);
}
}
class Read extends Thread {
DataInputStream in;
Socket socket;
public Read(Socket socket) {
AppendMessage("已开启read线程");
try {
this.socket = socket;
this.in = new DataInputStream(socket.getInputStream());
AppendMessage("已初始化Read\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
} catch (IOException e) {
}
}
@Override
public void run() {
while (true) {
try {
if(!ButtonMark)
this.stop();
String message = in.readUTF();
InformationCenter(message, socket);
} catch (IOException e) {
}
}
}
}
class Connect extends Thread{
@Override
public void run() {
try {
AppendMessage("打开服务??");
socket = new Socket(IP, Port);
if(ApplyConnect(socket))
{
ApplyUpdateList(socket);
read=new Read(socket);
read.start();
}
else {
throw new IOException();
}
} catch (Exception e) {
AppendMessage("连接服务器失败");
SwitchButton();
try {
socket.close();
} catch (IOException e1) {
}
this.stop();
}
}
}
}
后续
后续会写出基于UDP的多人聊天室(入数据库)本项目写得稀烂。
|