java之服务器端和客户端之间简单的通信

java之服务器端和客户端之间简单的通信

最近因为作业的需要,老师让用java语言写一个关于服务器端和客户端之间简单的通信,所以就有了这一篇文章
准备工作:
博主是在eclipse工具下进行操作的。
程序代码如下所示
1:客户端

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.*;
import java.net.*;
import javax.swing.*;

public class TCPJavaChatClient {

    public static void main(String[] args) {

        new TCPChatClient().launch();
    }
}

class TCPChatClient {
    private Frame f = null;
    private TextArea ta = null;
    private TextField tf = null;
    private Button send = null;
    private Button found = null;
    private DataInputStream dis = null;
    private DataOutputStream dos = null;
    private Socket s = null;

    public void launch() {
        creatUI();
        connection();
        new TCPClientReader().start();
        new TCPClientWriter().start();
    }

    public void creatUI() {
        f = new Frame();
        f.setTitle("客户端");
        tf = new TextField();
        ta = new TextArea();
        Panel p = new Panel(new BorderLayout());
        send = new Button("发送");
        found = new Button("查找");

        p.add(tf, BorderLayout.CENTER);
        p.add(send, BorderLayout.EAST);
        p.add(found, BorderLayout.NORTH);

        f.add(ta, BorderLayout.CENTER);
        f.add(p, BorderLayout.SOUTH);

        f.addWindowListener(new actionA());
        f.setSize(400, 400);
        f.setVisible(true);
    }

    public void close() {
        try {
            s.close();
            dis.close();
            dos.close();
        } catch (Exception e) {
            System.exit(-1);
        }
    }

    public void connection() {
        try {
            // 这里一旦new Socket成功后,便自动的请求建立连接,参数为目标IP地址和目标端口号  
            s = new Socket("127.0.0.1", 8812);

            // 这里是Socket对象调用getInputStream方法获取输入数据,然后用DataInputStream类的对象来接收  
            dis = new DataInputStream(s.getInputStream());
            // 这里Socket对象调用getOutputStream方法来写入数据,然后用DataOutputStream类的对象来接收  
            dos = new DataOutputStream(s.getOutputStream());
        } catch (Exception e) {
            System.out.println("建立连接失败");
            e.printStackTrace();
            System.exit(-1);
        }
    }

    class TCPClientReader extends Thread {
        public void run() {
            while (true) {
                try {
                    String str = dis.readUTF();
                    tf.setText("");
                    ta.append("对方说:" + str + "\n");
                    if (str.equalsIgnoreCase("再见")
                            || str.equalsIgnoreCase("88")) {
                        System.exit(-1);
                    }
                } catch (Exception e) {
                    JOptionPane.showMessageDialog(f, "已经断开连接");
                    return;
                }
            }
        }
    }

    class TCPClientWriter extends Thread {
        public void run() {
            tf.addActionListener(new TCPClientListener());
            send.addActionListener(new TCPClientListener());
        }
    }

    class TCPClientListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            try {
                String str = tf.getText();// 获取从键盘输入到文本框Text里的内容放到str  
                tf.setText("");// 设置文本内容为“”,即为空,每进入一次循环就将文本框里面的内容清空,可以再次输入  
                ta.append("回复:" + str + "\n");// 这里是文本区域调用append方法将输入文本框str内容添加进去,即显示出来  
                dos.writeUTF(str);
                if (str.equalsIgnoreCase("再见") || str.equalsIgnoreCase("88")) {
                    System.exit(-1);
                }
            } catch (Exception e2) {
                JOptionPane.showMessageDialog(f, "已经断开连接");
                return;
            }
        }

    }

}

class actionA implements WindowListener // 这里是定义一个实现窗口事件监听的类即add后面类名为事件监听器  
{
    // 下面是对窗口监听类中方法的重写,因为借口中的方法都是抽象的,所以使用时都需要重写,下面是java api文档中窗口事件监听器WindowListener中的相关方法  

    // 下面的方法是相应的事件操作,方法名可在API文档中发现  
    public void windowClosing(WindowEvent e)// 关闭   
    {
        System.exit(0);
    }

    public void windowOpened(WindowEvent e) {
    };

    public void windowIconified(WindowEvent e) {
    };// 最小化   

    public void windowDeiconified(WindowEvent e) {
    };// 最大化  

    public void windowClosed(WindowEvent e) {
    };

    public void windowActivated(WindowEvent e) {
    };

    public void windowDeactivated(WindowEvent e) {
    };
}

2:服务端

import java.awt.*;
import java.awt.Event;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.*;
import java.net.*;
import javax.swing.*;

//服务器与客户端最根本的区别就是建立连接那里,其他都一样  
public abstract class TCPJavaChatServer {

    public static void main(String[] args) {

        new ChatServer1().launch();

    }

}

//这里定义一个类完成主方法中的代码(窗口化界面的建立,相应的初始化和相应的方法类调用之类),使得主方法尽量的简洁  
class ChatServer1{

    //这里将需要用到的文本框,按钮,类的对象都定义成属性,可以减少后续代码;  
    private TextArea ta=null;
    private TextField tf=null;
    private Button send=null;
    private DataOutputStream dos=null;
    private DataInputStream dis=null;
    private ServerSocket ss=null;
    private Socket s=null;
    private Frame f=null;

    public void launch(){
        //该方法完成四个工作:创建图像界面UI;创建与客户端连接;启动服务器端的读取线程;启动服务器端的写入线程  
        creatUI();
        connection();
        //这里定义两个线程,是因为读写是两个线程进行不能用单线程完成  
        new TCPServerReader().start();
        new TCPServerWriter().start();
    }
    public void creatUI(){
        f=new Frame();
        f.setTitle("服务器端");
        ta=new TextArea();//这个为显示的文本区域  
        tf=new TextField();//这个为输入的文本框  

        //先定义一个Panel对象P而且布局管理器为BorderLayout即东西南北布局  
        Panel P=new Panel(new BorderLayout());
        send=new Button("发送");//这里定义一个发送按钮  

        P.add(tf,BorderLayout.CENTER);//往P中添加输入文本框tf,放在中间  
        P.add(send,BorderLayout.EAST);//发生按钮放在东边  

        f.add(ta,BorderLayout.CENTER);//在f中添加一个文本区域ta放在中间  
        f.add(P,BorderLayout.SOUTH);//而南边放P,即发送文本框和发送按钮都放到最底边  

        f.addWindowListener(new actionB());//增加窗口控制事件监听器  

        f.setSize(250, 250);//设置窗口大小  
        f.setVisible(true);
    }

    //这里是关闭的方法,对输入输出流和接受发送端的关闭异常捕获  
    public void close()
    {
        try{
            dos.close();
            dis.close();
            s.close();
            ss.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
            System.exit(-1);
        }

    }

    //建立连接方法,最主要的就是创建ServerSocket对象,然后调用accept方法返回给一个Socket对象,后面就是明确Socket对象s调用方法getInputStream和getOutputStream方法的返回值分别作为new DataInputStream和DataOutstream对象的参数  
    public void connection(){
        try{
            //创建服务器端  
            ss=new ServerSocket(8812);

            s=ss.accept();//调用accept方法后才开始不断监听客户端是否有发送连接请求,并且返回一个Socket对象,所以需要用一个Socket对象s来接收  

            //这里主要用到DataInputStream和DataOutputStream类中的读取和写入基本类型的方法  
            dis=new DataInputStream(s.getInputStream());
            dos=new DataOutputStream(s.getOutputStream());
        }
        catch(Exception e)
        {
            e.printStackTrace();
            System.out.println("建立连接失败");
            System.exit(-1);
        }

    }
    class TCPServerReader extends Thread{
        public void run(){
            //while1的死循环确保不在特定条件下保持通话的进行  
            while(true)
            {
                try{
                    String str=dis.readUTF();//定义一个String对象str用来接收dis.readUTF方法返回的内容  
                    tf.setText("");//setText让文本框显示信息  
                    ta.append("对方说:"+str+"\n");
                    if(str.equalsIgnoreCase("再见")||str.equalsIgnoreCase("88"))
                    {
                        close();//这里是调用close方法将Socket,ServerSocket,DataInputStream和DataOutputStream的对象都close了  
                        System.exit(-1);
                    }

                }
                catch(Exception e)
                {
                    JOptionPane.showMessageDialog(f, "已经断开连接");//这里是swing里面的类方法  
                    return;
                }
            }
        }
    }

    //发送数据的线程,这里需要事件处理即事件监听器,因为要涉及到写入数据并且点发送键发送出去  
    class TCPServerWriter extends Thread{
        public void run(){
            //第一个事件监听器是检测文本输入的事件  
            tf.addActionListener(new TCPListener());

            //第二事件监听器是检测按钮发送的事件  
            send.addActionListener(new TCPListener());

        }
    }

    class TCPListener implements ActionListener{
        public void actionPerformed(ActionEvent e){
            try{
                String str=tf.getText();//定义一个String类型用来接受文本框tf使用getText方法获取键盘输入的内容  
                tf.setText("");//这里再次把文本框设置为空,即清空,以便于下次输入  
                ta.append("回复:"+str+"\n");//文本区域调用append方法获取str内容并显示出来  
                dos.writeUTF(str);//这里就是dos调用WriteUTF把str写进去,便于传输  

                //这里若双方输入再见或者88,然后调用String的equalsIgnoreCase方法进行对比,该对较方法只比较内容  
                if(str.equalsIgnoreCase("再见")||str.equalsIgnoreCase("88")){
                    close();
                    System.exit(-1);//若满足则关闭对话框  
                }
            }
            catch(Exception e2){
                JOptionPane.showMessageDialog(f, "已经断开连接");//f是对话框,内容为断开连接  
                return;
            }
        }
    }
}


class actionB implements WindowListener //这里是定义一个实现窗口事件监听的类即add后面类名为事件监听器  
{
    //下面是对窗口监听类中方法的重写,因为接口中的方法都是抽象的,所以使用时都需要重写,下面是java api文档中窗口事件监听器WindowListener中的相关方法  

    //下面的方法是相应的事件操作,方法名可在API文档中发现  
    public void windowClosing(WindowEvent e)//关闭   
    {
        System.exit(0);
    }
    public void windowOpened(WindowEvent e){};
    public void windowIconified(WindowEvent e){};//最小化   
    public void windowDeiconified(WindowEvent e){};//最大化  
    public void windowClosed(WindowEvent e){};
    public void windowActivated(WindowEvent e){};
    public void windowDeactivated(WindowEvent e){};
}

3:结果
这里写图片描述
这里写图片描述

  • 17
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贾继康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值