服务端Socket配置

private static Map<String, Socket> sockets = new HashMap<>();//定义静态map集合

public static void main(String[] args) {//主函数

ServerSocket serverSocket = null;//服务端套接字定义

try {

serverSocket = new ServerSocket(8888);

// 指定服务器端口号为8888,端口范围0-65535

while (true) {//循环执行

Socket socket = s.accept();// 建立连接

ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());

//获取对象输入流
 Message message = (Message) ois.readObject();//读取流

sockets.put(message.getFrom(), socket);//将客户端查询的数据返回,并放入集合

ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());

//获取对象输出流

Set<String> sets = sockets.keySet();

List<String> list = new ArrayList<>();//定义list集合

String [] strs = new String[sets.size()];//获取sets的长度

for (String string : sets) {//循环sets集合

list.add(string);//将无序的set数组循环存入list集合

}

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

strs[i] = list.get(i);//无序集合有序化

}

message.setFirends(strs);//将集合中的数据加入好友列表集合中

oos.writeObject(message);//将流写入到客户端

new Thread() {//独立线程设置,防止线程冲突

public void run() {

while(true) {//循环流
 ObjectInputStream ois;//定义输入流

try {

ois = new ObjectInputStream(socket.getInputStream());

//将客户端输入流写入服务器流

Message message = (Message) ois.readObject();//读取输入流

if(message.getType() == Message.SEND) {//判断客户端是否请求发送信息

String to = message.getTo();//获取用户发送给的用户

Set<String> sets = sockets.keySet();//获取map存的数据

List<String> list = new ArrayList<>();//定义list字符串集合

String [] strs = new String[sets.size()];//定义字符串数组

for (String string : sets) {

list.add(string);//将循环数组放入集合

}

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

strs[i] = list.get(i);//集合有序化

}

message.setFirends(strs);//设置好友的信息

Socket socket = sockets.get(to);//获取发送给的人

if(socket != null) {//判断需要发送的人有没有

ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());

//获取输出流

oos.writeObject(message);//如果有就输出内容

oos.close();//关流

iso.close();//关流

} } } catch (IOException e) {//异常捕获

e.printStackTrace();

} catch (ClassNotFoundException e) {//异常捕获

e.printStackTrace();

} } }; }.start(); } } catch (IOException e) {//异常捕获

e.printStackTrace();

} catch (ClassNotFoundException e) {//异常捕获

e.printStackTrace();

}finally { }

客户端Socket

发送消息
public class Talk extends JFrame{//继承JFrame
private Socket socket;//定义套接字 
private JTextArea show;//定义消息的显示内容 
private JTextArea send;//发送消息的内容
private JButton sendButton;//定义发送按钮
private String username;//定义现在用户
private String to;//发送给的人
public Talk(String from ,String to,Socket socket) {
this.username = from;//给定义变量赋值
this.to = to;
this.setTitle(to);
this.socket = socket;
this.setSize(500, 500);//设置frame窗口大小
this.setLocationRelativeTo(null);//定义窗体位置
show = new JTextArea();//定义多行文本框对象
show.setPreferredSize(new Dimension(0, 250));//设定文本框大小
send = new JTextArea();   send.setBorder(BorderFactory.createLineBorder(Color.black));//设定边框颜色
sendButton = new JButton("发送");//定义按钮
sendButton.addActionListener(new ActionListener() {//设定按钮点击事件
@Override public void actionPerformed(ActionEvent e) { 
Message message = new Message();
message.setFrom(username);//设定窗体名字,登录用户名字
message.setTo(to);//发送给的人
message.setContent(send.getText());//发送的内容
message.setType(Message.SEND);//设定请求内容
ObjectOutputStream oos;//定义输出流
try {
oos = new ObjectOutputStream(socket.getOutputStream());oos.writeObject(message);
//将内容写入服务器
oos.flush();//清空流
showMessage(message.getContent());//展示消息文本框内容获取
send.setText("");//将发送文本框清空
} catch (IOException e1) { 
e1.printStackTrace(); //捕获异常
} } });
send.setPreferredSize(new Dimension(0, 50));//设定按钮大小 this.add(show,BorderLayout.NORTH);//消息展示框位置
this.add(send,BorderLayout.CENTER); //发送框内容
this.add(sendButton,BorderLayout.SOUTH);//按钮位置
this.setVisible(true);//显示窗体
 } 
public void showMessage (String content) {//定义方法
 show.append(content+"\n"); //将内容放入消息框
} 
}
登录
// 创建socket对象,指定服务器的ip地址,和服务器监听的端口号 客户端在new的时候,就发出了连接请求,服务器端就会进行处理,如果服务器端没有开启服务,那么 这时候就会找不到服务器,并同时抛出异常
public class Login extends JFrame{//登录类继承JFrame
private JTextField userNameField; //定义文本框
private JButton loginButton; //定义登录按钮
public Login() { //定义构造函数
setTitle("登录"); //窗体名设定
setSize(200,180); //设定窗体大小
setLocationRelativeTo(null); //居中 位置
Toolkit.getDefaultToolkit().getScreenSize(); 
//怎么获取屏幕的宽高   获取屏幕的尺寸 
JPanel panel = new JPanel(); //显示内容
add(panel); //窗体添加panel
panel.setLayout(null); //账号框 
userNameField = new JTextField(); //文本框
userNameField.setBounds(50, 30, 100, 30); //标签定位大小设定
panel.add(userNameField); //文本框加入panel
loginButton = new JButton("登录"); //登录按钮 
loginButton.addActionListener(new ActionListener() { //登录按钮事件
@Override public void actionPerformed(ActionEvent e) { 
String username = userNameField.getText(); //获取文本框内容
Message message = new Message(); 
message.setFrom(username); //设定当前用户
message.setType(Message.LOGIN); //设定功能
Socket socket = null; //设定套接字
try { 
socket = new Socket("127.0.0.1", 8888);//连接服务器 host,port
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); 
//获取输出流
oos.writeObject(message);//写出到客户端messge 
} catch (UnknownHostException e1) { //捕获异常
e1.printStackTrace(); 
} catch (IOException e1) {
e1.printStackTrace(); 
} 
Login.this.setVisible(false); //关闭登录框
new FriendList(username,socket); //好友列表调用
} }); 
loginButton.setBounds(50, 60, 100, 30); //设定按钮位置大小
panel.add(loginButton); //将按钮加入panel
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//点击关闭结束线程 
setVisible(true); //显示窗体
}}
好友列表
public class FriendList extends JFrame{//好友列表类
private Socket socket; //定义是套接字
private JPanel jPanel ; //定义显示
private String username; //定义显示的用户
private Map<String, Talk> talks = new HashMap<>();//定义map集合 存取聊天
private JList list; //列表显示定义
public FriendList(String username,Socket socket) {//定义好友列表构造 
this.username = username;  //给当前显示的用户赋值
this.socket = socket; //套接字赋值
setTitle(username); //设定窗体标题
jPanel = new JPanel(); //定义显示
this.add(jPanel); //将panel放入frame
ObjectInputStream ois; //定义输入了流
try { 
//读取好友列表 
ois = new ObjectInputStream(socket.getInputStream());//获取服务器值 
Message message = (Message) ois.readObject();//将服务器的值放入对象 
init(message.getFirends()); //调用方法
} catch (IOException e) { //捕获异常
e.printStackTrace(); 
} catch (ClassNotFoundException e) { 
e.printStackTrace(); 
} 
//开启线程接收聊天消息 
new Thread() { 
public void run() { 
while(true) { 
ObjectInputStream ois; //获取输入流
try { 
//读取好友列表 
ois = new ObjectInputStream(socket.getInputStream()); 
Message message = (Message) ois.readObject(); //读取服务器流内容流
init(message.getFirends()); //调用方法
Talk talk = talks.get(message.getFrom()); //从对象中获取当前用户
if(talk == null) { //判断
talk = new Talk(username,message.getFrom(), socket);//如果为空放入内容 talks.put(message.getFrom(), talk); 
} 
talk.showMessage(message.getContent()); 将内容传给talk
} catch (IOException e) { //捕获异常
e.printStackTrace(); 
} catch (ClassNotFoundException e) {
e.printStackTrace(); 
} } }; }.start(); 
setSize(230, 500); //设定窗体大小
setLocation(600,100); //设定窗体位置
setVisible(true); //显示窗体
} 
public void init(String[] firends) { 
jPanel.removeAll(); //情况好友列表
for (String string : firends) { 
System.out.println(string); //将更新内容显示在控制窗体
} 
list = new JList<>(firends); //将好友存入集合
list.addMouseListener(new MouseListener() { //鼠标事件
@Override public void mouseReleased(MouseEvent e) { } 
@Override public void mousePressed(MouseEvent e) { } 
@Override public void mouseExited(MouseEvent e) { } 
@Override public void mouseEntered(MouseEvent e) { } 
@Override public void mouseClicked(MouseEvent e) { 
if(e.getClickCount() == 2) { //双击
int index =list.locationToIndex(e.getPoint());//当前鼠标位置 
Talk talk = talks.get(firends[index]); //当前鼠标点击项
if(talk == null) { //判断
talk = new Talk(username,firends[index], socket);//显示聊天窗体 talks.put(firends[index], talk); //将内容放入集合
}else { 
talk.setVisible(true); //显示窗体
} } } }); 
jPanel.add(list); //显示好友
jPanel.updateUI(); //刷新
}}