Java——多人聊天室(基于TCP的网络编程——Socket)

转自: http://blog.csdn.net/qingsatianxia/article/details/50074821
服务端源代码:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;


public class Server extends JFrame implements ActionListener{


private static final long serialVersionUID = 1L;


private JTextField port; // 端口号文本框
private JButton start; // 启动服务器
private JButton stop; // 停止服务器
private JTextArea info; // 显示服务器消息
private JTextField msg; // 发送消息文本框
private JButton send; // 发送消息按钮


private List<Socket> sockets; // 保存服务器端所有Socket对象
private ServerSocket server; // 服务器ServerSocket对象


public Server() {
initFrame();
this.setVisible(true);
}


/**
* 初始化服务器界面
*/
private void initFrame() {
this.setTitle("服务器");
this.setSize(500, 500);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


// 窗体各组件对象
JLabel lblPort = new JLabel("监听端口:");
port = new JTextField("8899", 6);
port.setHorizontalAlignment(JTextField.CENTER);
start = new JButton("启动服务器");
stop = new JButton("停止服务器");
info = new JTextArea("日志:\n");
info.setEditable(false);
JScrollPane jsp = new JScrollPane(info);
msg = new JTextField(25);
send = new JButton("发送");


// 布局
JPanel pnlNorth = new JPanel();
pnlNorth.add(lblPort);
pnlNorth.add(port);
pnlNorth.add(start);
pnlNorth.add(stop);
this.add(pnlNorth, BorderLayout.NORTH);
this.add(jsp, BorderLayout.CENTER);
JPanel pnlSouth = new JPanel();
JLabel lblMsg = new JLabel("向所有人发送:");
pnlSouth.add(lblMsg);
pnlSouth.add(msg);
pnlSouth.add(send);
this.add(pnlSouth, BorderLayout.SOUTH);


//注册事件监听器
start.addActionListener(this);
stop.addActionListener(this);
send.addActionListener(this);
msg.addActionListener(this);
}


/**
* 启动服务器Socket资源信息
*/
private void startServer() {
String portStr=port.getText();
if(portStr.trim().length()==0||!portStr.trim().matches("\\d*"))
{
JOptionPane.showMessageDialog(Server.this, "端口号异常,请检查!");
return;
}
int portNum=Integer.parseInt(portStr);
try {
server=new ServerSocket(portNum);
info.append("服务器启动成功!\n");
//创建保存所有服务端Socket对象列表
sockets=new ArrayList<>();
start.setEnabled(false);
port.setEditable(false);
//启动线程实现监听,等待客户端连接
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Socket socket=server.accept();
sockets.add(socket);
new Thread(new TransferData(socket, info, sockets)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
} catch (IOException e) {
info.append("服务器启动异常:"+e.getMessage()+"\n");
}
}


/**
* 发送消息
*/
private void sendSMS()
{
for (Socket socket : sockets) {
try {
PrintWriter pw=new PrintWriter(socket.getOutputStream());
pw.println("服务器:"+msg.getText());
info.append("服务器:"+msg.getText()+"\n");
pw.flush();
} catch (IOException e) {
e.printStackTrace();
}


}
msg.setText(null);
}


/**
* 事件监听器
*/
public void actionPerformed(ActionEvent e) {
String action=e.getActionCommand();
switch (action) {
case "启动服务器":
startServer();
break;
case "停止服务器":
if(server!=null)
try {
if(server!=null)
{
server.close();
info.append("服务器停止运行!\n");
}
} catch (IOException e1) {
e1.printStackTrace();
}
break;
case "发送":
default:
sendSMS();
break;
}
}

/**
* 主方法,程序执行入口
* @param args
*/
public static void main(String[] args) {
new Server();
}
}


服务端接收数据并转发数据源代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.List;


import javax.swing.JTextArea;


public class TransferData implements Runnable{


private Socket socket;
private JTextArea info;
private List<Socket> sockets;
public TransferData(Socket socket, JTextArea info, List<Socket> sockets) {
super();
this.socket = socket;
this.info = info;
this.sockets = sockets;
}
@Override
public void run() {


BufferedReader br;
String nickName = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
nickName= br.readLine();
info.append(nickName+"上线了\n"+"\t上线人数为"+sockets.size()+"\n");
for (Socket soc : sockets) {
if(!this.socket.equals(soc))
{
PrintWriter pw=new PrintWriter(soc.getOutputStream());
pw.println(nickName+"上线了");
pw.flush();
}
}
while(true)
{
String read = br.readLine();
info.append(read+"\n");
//转发给其他客户端
for (Socket soc : sockets) {
if(!this.socket.equals(soc))
{
PrintWriter pw=new PrintWriter(soc.getOutputStream());
pw.println(read);
pw.flush();
}
}
}
} catch (IOException e) {
if("Connection reset".equals(e.getMessage()))
{
sockets.remove(socket);
info.append(nickName+"下线了\n"+"\t上线人数为"+sockets.size()+"\n");
for (Socket soc : sockets) {
if(!this.socket.equals(soc))
{
PrintWriter pw;
try {
pw = new PrintWriter(soc.getOutputStream());
pw.println(nickName+"下线了");
pw.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
}
}


}


客户端源代码:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;


public class Client extends JFrame implements ActionListener{


private static final long serialVersionUID = 1L;


private JTextField ip; // 连接服务器IP地址文本框
private JTextField port; // 连接服务器端口文本框
private JTextField nickName; // 昵称文本框
private JButton connect; // 连接按钮
private JTextArea info; // 显示所有群聊消息文本框
private JTextField msg; // 发送消息单行文本框
private JButton send; // 发送按钮
private Socket socket;

public Client() {
initFrame();
this.setVisible(true);
}


/**
* 初始化服务器界面
*/
private void initFrame() {
this.setTitle("客户端");
this.setSize(500, 500);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


// 创建所有界面组件对象
JLabel lblIp = new JLabel("IP:");
ip = new JTextField("10.7.172.68", 10);
ip.setHorizontalAlignment(JTextField.CENTER);
JLabel lblPort = new JLabel("端口:");
port = new JTextField("8899", 6);
port.setHorizontalAlignment(JTextField.CENTER);
JLabel lblNickname = new JLabel("昵称:");
nickName = new JTextField("小明", 6);
nickName.setHorizontalAlignment(JTextField.CENTER);
connect = new JButton("连接");
info = new JTextArea("聊天消息:\n");
info.setEditable(false);
JLabel lblMsg = new JLabel("向所有人说:");
msg = new JTextField(25);
send = new JButton("发送");


// 界面布局
JPanel pnlNorth = new JPanel();
pnlNorth.add(lblIp);
pnlNorth.add(ip);
pnlNorth.add(lblPort);
pnlNorth.add(port);
pnlNorth.add(lblNickname);
pnlNorth.add(nickName);
pnlNorth.add(connect);
this.add(pnlNorth, BorderLayout.NORTH);
this.add(info, BorderLayout.CENTER);
JPanel pnlSouth = new JPanel();
pnlSouth.add(lblMsg);
pnlSouth.add(msg);
pnlSouth.add(send);
this.add(pnlSouth, BorderLayout.SOUTH);

//注册事件监听器
connect.addActionListener(this);
send.addActionListener(this);
}


/**
* 主方法,程序执行入口
* @param args
*/
public static void main(String[] args) {
new Client();
}


/**
* 事件监听器
*/
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case "连接":
connectServer();
break;
case "发送":
default:
sendSms();
break;
}
}

/**
* 发送信息
*/
private void sendSms()
{
try {
PrintWriter pw=new PrintWriter(socket.getOutputStream());
pw.println(nickName.getText()+":"+msg.getText());
info.append(nickName.getText()+":"+msg.getText()+"\n");
pw.flush();
} catch (IOException e) {
e.printStackTrace();
}
msg.setText(null);
}

/**
* 连接服务器
*/
private void connectServer()
{
String ipNet=ip.getText();
String portStr=port.getText();
if(ipNet==null||portStr==null)
{
JOptionPane.showMessageDialog(Client.this, "IP或端口号异常,请检查!");
return;
}
int portNum=Integer.parseInt(portStr);
try {
//创建socket对象
socket=new Socket(ipNet, portNum);
socket.setSoTimeout(60*1000);//设置连接超时
PrintWriter pw=new PrintWriter(socket.getOutputStream());
pw.println(nickName.getText());
pw.flush();
new Thread(new Runnable() {
public void run() {//读取服务器发送来的数据
BufferedReader br;
try {
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {//死循环,使用线程就是让死循环停止
String read=br.readLine();
info.append(read+"\n");
}
} catch (IOException e) {
info.append("服务器断开,请稍后重新连接!\n");
//br.close();  
}

}
}).start();
info.append("连接服务器成功\n");
} catch(SocketException e){
info.append("套接字异常:"+e.getMessage()+"\n");
}catch (UnknownHostException e) {
info.append("未知服务器异常:"+e.getMessage()+"\n");
}catch (IOException e) {
info.append("连接服务器异常:"+e.getMessage()+"\n");
}
}
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值