一个简单的聊天程序,有客户端和服务端,可以进行群聊功能。只有两个文件,涉及Scocket和多线程知识。
话不多说直接上代码
服务器端代码:
/**
* Created by lean on 2018/7/30.
*/
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.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Server extends JFrame implements ActionListener{
private Map clients = new HashMap();
private JTextArea msg = new JTextArea("消息接收器\r\n");
private JButton msgSend = new JButton("发送群消息");
public Server() {
// TODO Auto-generated constructor stub
this.setVisible(true);
this.setSize(500, 650);
this.setLayout(new FlowLayout());
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
// TODO Auto-generated method stub
super.windowClosing(arg0);
System.exit(0);
}
});
msgSend.addActionListener(this);
msgSend.setActionCommand("sendMsg");
msg.setAutoscrolls(true);
msg.setColumns(40);
msg.setRows(30);
JScrollPane spanel = new JScrollPane(msg);
this.add(spanel);
this.add(msgSend);
}
public static void main(String[] args){
new Server().listenClient();
}
public void listenClient(){
int port = 8899;
String temp = "";
// 定义一个ServerSocket监听在端口8899上
try {
ServerSocket server = new ServerSocket(8899);
// server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的
while (true) {
System.out.println("服务器端正在监听");
Socket socket = server.accept();
temp = "客户端"+socket.getPort()+":连接";
clients.put(socket.getPort(), socket);
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 keset = this.clients.keySet();
java.util.Iterator 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())){
System.out.println("开始向客户端群发消息");
Set keset = this.clients.keySet();
java.util.Iterator iter = keset.iterator();
while(iter.hasNext()){
int key = iter.next();
Socket socket = clients.get(key);
try {
if(socket.isClosed() == false){
if(socket.isOutputShutdown() == false){
temp = "向客户端"+socket.getPort()+"发送消息";
System.out.println(temp);
Writer writer = new OutputStreamWriter(
socket.getOutputStream());
this.apppendMsg(temp);
writer.write("来自服务器的问候");
writer.flush();
}
}
} catch (SocketException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
}
class mythread extends Thread{
private Socket socket = null;
private Server server = null;
private InputStreamReader reader = null;
char chars[] = new char[64];
int len;
private String temp = null;
public mythread(Socket socket, Server 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)) != -1) {
temp = new String(chars, 0, 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 = "线程"+this.getId()+"——>关闭";
// System.out.println(temp);
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();
}
}
}
}
}
客户端代码:
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.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class CKClient extends JFrame implements ActionListener{
// 为了简单起见,所有的异常都直接往外抛
String host = "127.0.0.2"; // 要连接的服务端IP地址
int port = 8899; // 要连接的服务端对应的监听端口
mythread1 thread = null;
Socket client = null;
Writer writer = null;
private JTextArea msg = new JTextArea("客户端消息接收器\r\n");
private JTextArea input = new JTextArea();
private JButton msgSend = new JButton("发送群消息");
public CKClient() {
// TODO Auto-generated constructor stub
initSocket();
this.setVisible(true);
this.setSize(550, 750);
this.setResizable(false);
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(0);
}
});
input.setColumns(40);
input.setRows(10);
input.setAutoscrolls(true);
msgSend.addActionListener(this);
msgSend.setActionCommand("sendMsg");
msg.setAutoscrolls(true);
msg.setColumns(40);
msg.setRows(25);
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 {
new CKClient();
}
public void initSocket(){
try {
client = new Socket(this.host, this.port);
writer = new OutputStreamWriter(client.getOutputStream());
// 建立连接后就可以往服务端写数据了
thread = new mythread1(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 mythread1 extends Thread {
private Socket socket = null;
private Reader reader = null;
private int len = 0;
char chars[] = new char[64];
private CKClient client = null;
private String temp = "";
public mythread1(Socket socket, CKClient 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)) != -1) {
temp = "服务器说——>"+":"+ new String(chars, 0, 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();
}
}
}
}