java Socket多线程聊天程序

参考JAVA 通过 Socket 实现 TCP 编程

参考java Socket多线程聊天程序(适合初学者)

以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。

一个非常简单的java聊天程序,有客户端和服务器端,目前只有群聊功能,其他的所有功能都可以在这个基础上添加,现在我分享出来主要是为了保持一个最简单的java聊天程序便于初学者学习,界面也非常的简洁,只有两个文件,主要是用了socket,java多线程,知识点不是很多,很适合初学者

java Socket多线程聊天程序

服务器端程序:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set; /**
* @Auther: 李景然
* @Date: 2018/5/17 10:12
* @Description:
*/
public class TKServer extends JFrame implements ActionListener { private Map<Integer, Socket> clients = new HashMap<Integer, Socket>();
private JTextArea msg = new JTextArea("服务器消息接收器\r\n\n");
private JTextArea input = new JTextArea();
private JButton msgSend = new JButton("发送群消息"); public TKServer() {
// TODO Auto-generated constructor stub
this.setVisible(true);
this.setTitle("服务器");
this.setSize(, );
this.setResizable(true);
this.setLayout(new FlowLayout());
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
// TODO Auto-generated method stub
super.windowClosing(arg0);
System.exit();
}
});
input.setColumns();
input.setRows();
input.setAutoscrolls(true);
msgSend.addActionListener(this);
msgSend.setActionCommand("sendMsg");
msg.setAutoscrolls(true);
msg.setColumns();
msg.setRows(); JScrollPane spanel = new JScrollPane(msg);
JScrollPane editpanel = new JScrollPane(input);
this.add(spanel);
this.add(editpanel);
this.add(msgSend);
} public static void main(String[] args) { new TKServer().listenClient();
} public void listenClient() { String temp = "";
try {
//server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的
// 定义一个ServerSocket监听在端口8899上
ServerSocket server = new ServerSocket();
while (true) {
System.out.println("服务器端正在监听");
Socket socket = server.accept();
clients.put(socket.getPort(), socket);
temp = "客户端" + socket.getPort() + " 连接";
this.apppendMsg(temp);
new mythread(socket, this).start();
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
} public void apppendMsg(String msg) { this.msg.append(msg + "\r\n");
} public void sendMsgToAll(Socket fromSocket, String msg) { Set<Integer> keset = this.clients.keySet();
java.util.Iterator<Integer> iter = keset.iterator();
while (iter.hasNext()) {
int key = iter.next();
Socket socket = clients.get(key);
if (socket != fromSocket) {
try {
if (socket.isClosed() == false) {
if (socket.isOutputShutdown() == false) { Writer writer = new OutputStreamWriter(
socket.getOutputStream());
writer.write(msg);
writer.flush();
}
}
} catch (SocketException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
} @Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub String temp = "";
if ("sendMsg".equals(e.getActionCommand())) {
if ((temp = this.input.getText()) != null) {
System.out.println("开始向客户端群发消息");
this.apppendMsg("服务器-->" + temp);
Set<Integer> keset = this.clients.keySet();
java.util.Iterator<Integer> iter = keset.iterator();
while (iter.hasNext()) {
int key = iter.next();
Socket socket = clients.get(key);
try {
Writer writer = new OutputStreamWriter(socket.getOutputStream());
writer.write(temp);
writer.flush();
} catch (SocketException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
this.input.setText("");
}
}
}
} class mythread extends Thread { private Socket socket = null;
private TKServer server = null;
private InputStreamReader reader = null;
char chars[] = new char[];
int len;
private String temp = null; public mythread(Socket socket, TKServer server) {
// TODO Auto-generated constructor stub this.socket = socket;
this.server = server;
init();
} private void init() { try {
reader = new InputStreamReader(socket.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} @Override
public void run() {
// TODO Auto-generated method stub System.out.println("子线程开始工作");
while (true) {
try {
System.out.println("服务器 线程" + this.getId() + "-->开始从客户端读取数据——>");
while ((len = ((Reader) reader).read(chars)) != -) {
temp = new String(chars, , len);
System.out.println("客户端" + socket.getPort() + "说-->" + temp);
server.apppendMsg("客户端" + socket.getPort() + "说-->" + temp);
server.sendMsgToAll(this.socket, "客户端" + socket.getPort() + "说-->" + temp);
}
if (socket.getKeepAlive() == false) {
((Reader) reader).close();
temp = "客户端" + socket.getPort() + "-->退出";
server.apppendMsg(temp);
socket.close();
this.stop();
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
try {
((Reader) reader).close();
socket.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
}

客户端程序:

/**
* @Auther: 李景然
* @Date: 2018/5/17 10:15
* @Description:
*/ import java.awt.FlowLayout; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.Socket;
import java.net.UnknownHostException; import javax.swing.*; public class TKClient extends JFrame implements ActionListener { // 为了简单起见,所有的异常都直接往外抛
String host = "127.0.0.1"; // 要连接的服务端IP地址
int port = ; // 要连接的服务端对应的监听端口
mythread thread = null;
Socket client = null;
Writer writer = null; private JTextArea msg = new JTextArea("客户端消息接收器\r\n\n");
private JTextArea input = new JTextArea();
private JButton msgSend = new JButton("发送群消息"); public TKClient() {
// TODO Auto-generated constructor stub initSocket();
this.setVisible(true);
this.setTitle("客户端");
this.setSize(, );
this.setResizable(true);
this.setLayout(new FlowLayout());
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
// TODO Auto-generated method stub
super.windowClosing(arg0);
try {
if (client != null) {
client.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (thread != null) {
thread.stop();
}
System.exit();
}
});
input.setColumns();
input.setRows();
input.setAutoscrolls(true);
msgSend.addActionListener(this);
msgSend.setActionCommand("sendMsg");
msg.setAutoscrolls(true);
msg.setColumns();
msg.setRows();
JScrollPane spanel = new JScrollPane(msg);
JScrollPane editpanel = new JScrollPane(input);
this.add(spanel);
this.add(editpanel);
this.add(msgSend);
} /**
* @param args
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub new TKClient();
} public void initSocket() { try {
client = new Socket(this.host, this.port);
writer = new OutputStreamWriter(client.getOutputStream());
// 建立连接后就可以往服务端写数据了
thread = new mythread(client, this);
thread.start();
this.appendMsg("已连上服务器");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
this.appendMsg("不能连接上服务器");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
this.appendMsg("不能连接上服务器");
}
} public void appendMsg(String msg) { this.msg.append(msg + "\r\n");
} @Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub String temp = "";
try {
if ("sendMsg".equals(e.getActionCommand())) {
if ((temp = this.input.getText()) != null) {
writer.write(temp);
writer.flush();
this.appendMsg("我(" + this.client.getLocalPort() + ")说——>" + temp);
this.input.setText("");
}
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
} class mythread extends Thread { private Socket socket = null;
private Reader reader = null;
private int len = ;
char chars[] = new char[];
private TKClient client = null;
private String temp = ""; public mythread(Socket socket, TKClient client) {
// TODO Auto-generated constructor stub this.socket = socket;
this.client = client;
try {
reader = new InputStreamReader(socket.getInputStream());
} catch (Exception e) {
// TODO: handle exception
}
} @Override
public void run() {
// TODO Auto-generated method stub super.run();
System.out.println("客户端 子线程" + this.getId() + "-->开始工作");
while (true) {
try {
if (socket.isClosed() == false) {
if (socket.isInputShutdown() == false) {
while ((len = ((Reader) reader).read(chars)) != -) {
temp = "服务器说——>" + new String(chars, , len);
client.appendMsg(temp);
System.out.println();
}
}
} else {
if (socket.getKeepAlive() == false) {
reader.close();
socket.close();
this.stop();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
上一篇:Android OpenGL ES 开发教程 从入门到精通


下一篇:改变JVM中的参数以提高Eclipse的运行速度