java socket编程思路_Java实现Socket网络编程(四)

在看到本文之前,如果读者没看过笔者的前文Java实现Socket网络编程(三) ,请先翻阅。

下面,我们来实现服务器单体发送和广播发送:

我们为JList客户端列表设置监听,在每次点击触发时,先默认设置所有Socket未选中,避免错乱,然后获取全部已选中下标,并做好标记。笔者此处采用HashMap存储Socket,如Socket被选中,其对应Value为true,反之为false。

// 添加监听

clientList.addListSelectionListener(new ListSelectionListener() {

@Override

public void valueChanged(ListSelectionEvent e) {

// 先默认把所有Socket未选中

resetSocket(ListenThread.clientSockets);

// 获取全部已选中下标

int[] selecteds = clientList.getSelectedIndices();

for (int i = 0; i < selecteds.length; i++) {

// 获取所选中项的HashMap

HashMap map = ListenThread.clientSockets

.get(selecteds[i]);

// 用迭代器获取HashMap的Key,即所选中的Socket

Iterator iter = map.entrySet().iterator();

Map.Entry entry = (Entry) iter

.next();

Socket key = (Socket) entry.getKey();

// 把所选中的Socket设置为true

map.replace(key, true);

}

}

});

然后,在点击发送消息的按钮时,根据之前在JList中标记的Socket,向指定客户端发送消息。

// 设置发送消息监听

jbSendMessage.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

if (jtaSendMessage.getText().equals("")) {

JOptionPane.showMessageDialog(null, "发送内容不能为空!");

return;

}

if (jtaSendMessage.getText().length() > 5000) {

JOptionPane.showMessageDialog(null, "发送数据过大,最大不能超过5000字!");

return;

}

// 取得要发送的消息

// 代表服务器正常连接

String message = Common.OK;

String t = "server " + Common.IP + ":" + Common.PORT + " "

+ jtaSendMessage.getText();

OutputStreamWriter outstream = null;

// 将信息发送给每个选中的客户端

for (int i = 0; i < ListenThread.clientSockets.size(); i++) {

try {

HashMap map = ListenThread.clientSockets

.get(i);

// 用迭代器获取HashMap的Key,即所选中的Socket

Iterator iter = map.entrySet().iterator();

Map.Entry entry = (Entry) iter

.next();

// 如果Socket已选中

if ((Boolean) entry.getValue()) {

Socket key = (Socket) entry.getKey();

outstream = new OutputStreamWriter(key

.getOutputStream(), "GBK");

outstream.write(message);

outstream.flush();

}

} catch (IOException e1) {

if (outstream != null)

try {

outstream.close();

} catch (IOException e2) {

e2.printStackTrace();

}

e1.printStackTrace();

}

}

// 清空文本

jtaSendMessage.setText(null);

}

});

为了实现客户端自动连接服务器,我们要为客户端实现一个子线程,用于轮询检测服务器是否已启动:

public void run() {

while (true) {

// 窗口关闭则直接退出循环,避免在关闭过程中再次连接服务器

if (ClientMain.isWindowClosing)

break;

try {

if (ClientMain.mSocket == null || ClientMain.mSocket.isClosed()) {

ClientMain.isConnected = false;

ClientMain.jlConnect.setText("Out Of Connect.");

}

if (!ClientMain.isConnected) {

Socket socket = new Socket(Common.IP, Common.PORT);

ClientMain.mSocket = socket;

// 启动客户端连接子线程

new Thread(new ClientReceivedThread(socket)).start();

ClientMain.isConnected = true;

ClientMain.jlConnect.setText("Success Connect.");

}

} catch (Exception e) {

// 无法连接服务器

ClientMain.isConnected = false;

ClientMain.jlConnect.setText("Out Of Connect.");

e.printStackTrace();

}

}

}

在这里,读者可能会遇到一个问题,客户端是如何检测到服务器断开,而服务器又如何检测到客户端断开呢?

笔者为读者提供两种方法:

1、检测读写错误,在BufferedReader的read()方法中,如果发生读写错误,便能捕获到。

2、发送心跳包检测

对于方法1,服务器和客户端实现的方法一样

对于方法2,服务器应发送心跳包0,客户端应发送心跳到0xFF

mSocket.sendUrgentData(0);//服务器检测客户端断开

mSocket.sendUrgentData(0xFF);//客户端检测服务器断开

当捕获到异常时,便能得知对方断开。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值