java之服务器端和客户端之间简单的通信 雨点打透心脏的1/2处 2022-05-25 10:53 230阅读 0赞 ## 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:结果 ![这里写图片描述][70] ![这里写图片描述][70 1] [70]: /images/20220525/05e008d343b849af8a8c86372e4dc2b1.png [70 1]: /images/20220525/b2812e6c3d1443c7bdbf82badb5d73f8.png
还没有评论,来说两句吧...