【Java】socket编程实现简单的C/S结构

  1. 程序需求
    客户端程序编写包括两部分,客户端界面和客户端通信线程。由于要使用图像化界面,所以网络通信的功能往往都是需要开新的线程来实现需求。
    客户端需要实现往服务端发送消息的功能,并且可以记录服务端的反馈信息。
    服务端程序需要实现一个持续提供服务的进程。接受客户端发送的信息,并反馈信息回客户端程序。
  2. 客户端界面
    详细注释已经添加,注意查看注释标记的信息
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @author Yixiang
 * @date 2021/5/25
 */

public class Client extends JFrame {
    public static void main(String[] args){
        new Client();
    }

    //构造方法
    public Client(){
        initFrame();
    }

    //初始化图形化界面
    public void initFrame(){
        this.setLayout(new BorderLayout());
        this.setTitle("Client");
        this.setDefaultLookAndFeelDecorated(true);
        this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
        this.setBounds(600,300,500,200);

        JPanel jPanel=new JPanel();
        jPanel.setLayout(new FlowLayout());

        JTextField jTextField_1=new JTextField(31);
        JButton jButton=new JButton("发送");

        JTextArea jTextArea=new JTextArea();
        //jTextArea.setPreferredSize(new Dimension(460,150));
        jTextArea.setEditable(false);//设置为不可编辑
        jTextArea.setLineWrap(true);//文字比控件的宽度还长时会自动换行
        jTextArea.setWrapStyleWord(true);//在单词边界换行,而不是粗暴的直接在字符边界换行

        //为发送按钮添加点击事件
        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(!jTextField_1.getText().equals("")){
                    Thread thread=new ClientThread(jTextField_1,jTextArea);//创建新的客户端socket网络通信线程
                    thread.start();//客户端socket网络通信线程启动
                }
            }
        });

        //为JTextArea添加滚动条
        JScrollPane jScrollPane=new JScrollPane(jTextArea);//jTextArea就不能在设置边界大小了
        jScrollPane.setPreferredSize(new Dimension(460,100));
        jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        jPanel.add(jTextField_1);
        jPanel.add(jButton);
        jPanel.add(jScrollPane);

        this.add(jPanel,BorderLayout.CENTER);
        this.setVisible(true);
    }
}
  1. 客户端socket网络通信线程
import javax.swing.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * @author Yixiang
 * @date 2021/5/25
 */

public class ClientThread extends Thread{
    JTextField jTextField;
    JTextArea jTextArea;

    //构造方法,把客户端界面的控件对象传入进来
    public ClientThread(JTextField jTextField,JTextArea jTextArea){
        this.jTextField=jTextField;
        this.jTextArea=jTextArea;
    }


    @Override
    public void run() {
        String readLine = "default";//设置默认值
        String inTemp = null;
        //String outTemp = null;
        String turnLine = "\n";
        final String client = "Client:";
        final String server = "Server:";
        //目的端口
        int port = 4000;
        //目的地址
        byte ipAddressTemp[] = {127, 0, 0, 1};
        try{
            //从jTextField把值拿出来
            readLine=jTextField.getText();
            //jTextField值要清空,以便下一次输入
            jTextField.setText("");
            InetAddress ipAddress = null;
            ipAddress = InetAddress.getByAddress(ipAddressTemp);
            //创建指向服务器的地址和端口
            Socket socket = null;
            //开启一个新的socket
            socket = new Socket(ipAddress, port);
            

            //接受服务器送过来数据的流
            BufferedReader socketIn = null;
            socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //往服务器端送数据的流
            PrintWriter socketOut = null;
            socketOut = new PrintWriter(socket.getOutputStream());

            //往服务器端送入数据
            socketOut.println(readLine);
            socketOut.flush();

            //服务端返回数据后,socketIn接收返回的数据
            inTemp=socketIn.readLine();
            if(inTemp!=null){
                jTextArea.append(inTemp+"\n");
            }
            //System.out.println("inTemp is "+inTemp);

            socketIn.close();
            socketOut.close();
            socket.close();//socket关闭
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  1. 服务端程序
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author Yixiang
 * @date 2021/5/25
 */
public class Server {
    public static void main(String[] args) throws IOException {
        String readline=null;
        String inTemp=null;
        
        //创建服务端的端口地址
        int port=4000;
        ServerSocket serverSocket=new ServerSocket(port);//serverSocket需要持久打开
        
        while(true) {

            Socket socket=serverSocket.accept();//serverSocket需要持续接收新的socket请求
            BufferedReader socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));//接收客户端发送的信息
            PrintWriter socketOut = new PrintWriter(socket.getOutputStream());//输出流,往客户端发送信息时使用

            inTemp=socketIn.readLine();
            if(inTemp!=null&&inTemp.equals("bye")){
                socketIn.close();
                socketOut.close();
                socket.close();
                break;
            }
            else if(inTemp!=null&&!inTemp.equals("")&&!inTemp.equals("null")){
                //查看客户端socket请求的ip地址和端口信息
                InetAddress inetAddress=socket.getInetAddress();
                String ip=inetAddress.getHostAddress();
                int clientPort=socket.getPort();
                System.out.println("内容为:"+inTemp+"\n"+"ip:"+ip+"\n"+"clientPort:"+clientPort);

                readline="server收到了!";
                socketOut.println(readline+inTemp);//往客户端发出反馈信息
                socketOut.flush();
            }

            socketIn.close();
            socketOut.close();
            socket.close();
            //注意在while循环中不要关闭serverSocket

        }
        serverSocket.close();

    }
}

  1. 运行结果
    在这里插入图片描述
  • 5
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
实现一个Java GUI的C/S结构的简易聊天室,首先需要建立服务器端和客户端。服务器端负责接收和转发消息,客户端负责发送和接收消息。 服务器端的实现: 1. 创建一个ServerSocket对象来监听指定的端口号。 2. 使用多线程,不断循环接收客户端的连接请求,每次接收到连接请求时,创建一个新的线程处理该连接。 3. 每个连接使用一个Socket对象来进行通信。 4. 使用一个ArrayList或HashMap来保存已连接的客户端Socket对象,并在线程中处理客户端的请求。 5. 接收到客户端发送的消息后,将该消息转发给其他的客户端。 客户端的实现: 1. 创建一个Socket对象,并连接到服务器的IP地址和端口号。 2. 使用多线程,一个线程负责接收服务器发送的消息,一个线程负责发送客户端输入的消息。 3. 接收到服务器发送的消息后,在GUI界面上展示。 4. 输入消息后,通过Socket对象将消息发送给服务器。 需要注意的是,服务器端和客户端之间的通信需要使用流来进行读写。通过在GUI界面上添加输入框、发送按钮和显示消息的区域,可以实现用户的输入和消息的展示。 通过以上步骤,即可实现一个简易的C/S结构的聊天室。当有客户端发送消息时,服务器会接收并转发给其他客户端,其他客户端收到消息后也会显示在界面上。这样就可以实现用户之间的即时通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值