/* *作者:呆萌老师 *☑csdn认证讲师 *☑51cto高级讲师 *☑腾讯课堂认证讲师 *☑网易云课堂认证讲师 *☑华为开发者学堂认证讲师 *☑爱奇艺千人名师计划成员 *在这里给大家分享技术、知
/*
*作者:呆萌老师
*☑csdn认证讲师
*☑51cto高级讲师
*☑腾讯课堂认证讲师
*☑网易云课堂认证讲师
*☑华为开发者学堂认证讲师
*☑爱奇艺千人名师计划成员
*在这里给大家分享技术、知识和生活
*各种干货,记得关注哦!
*/
基于TCP协议书写的服务端,服务端开启之后,只能给一个客户端提供服务,在服务结束之后,服务端就关闭了,其他的客户端就无法在连接到当前这个服务端。
解决一个服务端,可以同时(并发)给多个客户端提供服务:
我们需要在服务端开启多线程,只要有一个客户端连接到服务端,那么这是服务端内部就应该开启一个线程,为这个客户端服务,然后服务端继续等待下一个客户端的连接,只要有客户端连接到服务端,服务端就需要开启线程为当前连接到的这个客户端进行服务。
开启线程:直接new Thread 调用start,获取使用线程池都可以完成。
线程的任务:在服务端获取到客户端对象之后,后续的所有操作,都是基于当前这个客户端而进行,那么当前这些操作都属于线程的任务。
服务端
import java.io.BufferedReader;import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
//聊天室服务器端
public class Server {
//存放所有链接上当前服务器的客户端
private List<Socket> clientSockets=new ArrayList<Socket>();
public Server()
{
try {
//1.创建服务器端socket
ServerSocket serverSocket=new ServerSocket(9999);
while(true)
{
//2.接收客户端的socket
Socket socket= serverSocket.accept();
//3.存入集合中
this.clientSockets.add(socket);
//4.开一个线程处理客户端发送过来的消息
ReceiveThread thread=new ReceiveThread(socket);
thread.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//创建一个线程 接收客户端的socket
class ReceiveThread extends Thread
{
private Socket currentSocket;
public ReceiveThread(Socket socket)
{
this.currentSocket=socket;
}
public void run()
{
try {
//获得当前客户端中拿到的消息
InputStream is= this.currentSocket.getInputStream();
//获得输入流
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(is));
String msg=null;
while((msg=bufferedReader.readLine())!=null)
{
//群发给所有的客户端
for(Socket socket :clientSockets)
{
PrintWriter pw =new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
pw.println(msg);
pw.flush(); //发送到客户端
//不要关闭输出流 ftp协议中 规定 如果关闭当前socket输出流 则意味着对应的socket关闭
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
客户端
import java.awt.GridLayout;import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class Login extends JFrame{
private JLabel unameJLabel;
private JLabel pwdJLabel;
private JTextField unameJTextField;
private JTextField pwdJTextField;
private JButton loginJButton;
private JButton cancelJButton;
public Login()
{
super("IT全明星聊天室");
this.unameJLabel= new JLabel("用户名:");
this.pwdJLabel=new JLabel("密码:");
this.unameJTextField=new JTextField();
this.pwdJTextField=new JTextField();
this.loginJButton=new JButton("登录");
this.cancelJButton=new JButton("取消");
this.setSize(300,200);
this.setLayout(new GridLayout(3,2));
this.add(unameJLabel);
this.add(unameJTextField);
this.add(pwdJLabel);
this.add(pwdJTextField);
this.add(loginJButton);
this.add(cancelJButton);
//给按钮做监听事件
MyEvent myEvent=new MyEvent();
this.loginJButton.addActionListener(myEvent);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
//监听单击事件
class MyEvent implements ActionListener
{
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
//1.获得用户名
String loginUname=unameJTextField.getText();
try {
//2.创建socket链接服务器端
Socket socket=new Socket("127.0.0.1", 9999);
//3.跳转到聊天室页面
new Client(socket,loginUname);
//4.当前登录窗口可以关闭
dispose();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
JOptionPane.showMessageDialog(null,"找不到服务器");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch blockimport java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
public class Client extends JFrame {
private JScrollPane topPanel; //滚动面板 用来放消息列表
private JPanel bottomPanel; //发送消息的面板
private JTextArea msgList; //存放消息列表 不可编辑
private JTextField msgText; //写消息的文本框
private JButton sendButton; //发送按钮
private Socket socket;
private String uname;
public Client(Socket socket,String uname)
{
super(uname);
this.socket=socket;
this.uname=uname;
//创建组件对象
this.topPanel=new JScrollPane();
this.bottomPanel=new JPanel();
this.msgList=new JTextArea();
this.msgText=new JTextField();
this.sendButton=new JButton("发送");
//设置属性 (绝对布局)
this.topPanel.setLayout(null);
this.bottomPanel.setLayout(null);
this.topPanel.setBounds(0, 0, 1000, 500);
this.msgList.setBounds(30,30,940,440);
this.bottomPanel.setBounds(0, 500, 1000, 100);
this.msgText.setBounds(30, 510, 700, 80);
this.sendButton.setBounds(750, 510, 200, 80);
//添加组件到窗口中
this.topPanel.add(msgList);
this.bottomPanel.add(msgText);
this.bottomPanel.add(sendButton);
this.add(topPanel);
this.add(bottomPanel);
//设置窗口属性
this.setSize(1000,600);
this.setLocationRelativeTo(null);
this.setVisible(true);
//开启一个线程 接收服务器端发回的消息
ReceiveThread receiveThread=new ReceiveThread();
receiveThread.start();
//对发送按钮做监听器
MyEvent myEvent=new MyEvent();
this.sendButton.addActionListener(myEvent);
}
class MyEvent implements ActionListener
{
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
//1.获得文本框的消息内容
String msg= msgText.getText();
//格式化日期
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
String time=simpleDateFormat.format(new Date());
msg=time+uname+"说:"+msg;
//2.发送到服务器端
try {
PrintWriter pw=new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
pw.println(msg);
pw.flush(); //不能关 socket中的输出流
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//创建接收从服务器端返回的消息 的线程类
class ReceiveThread extends Thread{
public void run()
{
BufferedReader bufferedReader;
try {
//从服务器端读消息进来
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg=null;
while((msg=bufferedReader.readLine())!=null)
{
msgList.append(msg+"\n");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
更多了解
https://edu.51cto.com/lecturer/14175030.html