Java实现TCP一对一通信,实现UDP群聊通信

TCP一对一通信:

实现服务端对话框:

其中可自由更改对话框的样式


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class QqMain extends JFrame implements ActionListener{public static void main(String[] args){InetAddress ia = null;try {ia = ia.getLocalHost();String localip = ia.getHostAddress();System.out.println("本机的ip是 :" + localip);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}new QqMain();}// 说明:一个类需要页面的显示,则那个类要继承JFrame。// 属性// 文本域private JTextArea jta;// 滚动条private JScrollPane jsp;// 面板里面是文本框和按钮private JPanel jp;private JTextField jtf;private JButton jb ;BufferedWriter bw  = null;// 构造器public QqMain(){// 初始化上面的属性jta = new JTextArea();// 将文本域添加到滚动条中jsp = new JScrollPane(jta);jp = new JPanel();jtf =new JTextField(15);jb = new JButton("发送");// 把按钮和文本框添加到面板中jp.add(jtf);jp.add(jb);// 把滚动条和面板添加到JFrame中去this.add(jsp,BorderLayout.CENTER); //这个设置在中间this.add(jp,BorderLayout.SOUTH); //南this.setTitle("qq聊天");this.setSize(500,500);this.setLocation(200, 200);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);/***********TCP协议*************/jb.addActionListener(this);  // 这是按钮点击使用// 回车键的监听事件 在接口KeyListener中//jtf.addKeyListener(this);jtf.addKeyListener(new KeyAdapter() {public void keyTyped(KeyEvent e) {if((char)e.getKeyChar()==KeyEvent.VK_ENTER) {useVoid();}}});try{// 1.创建一个服务端的套接字ServerSocket serverSocket = new ServerSocket(8888);//2.等待客户端的连接Socket socket = serverSocket.accept();// 3.获取socket通道的输入流(输入流的读取方式为一行一行的读取方式 ----> readLine())BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 4.获取通道的输入流(也是一行一行的写出  BufferedWriter ->newLine())// 当用户点击“发送”按钮的时候才会,写出数据bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));String line = null;while((line = br.readLine()) !=null){// 将读取的数据拼接到文本域中显示jta.append(line + "\n");}// 5.关闭socket通道serverSocket.close();}catch(IOException e){e.printStackTrace();}/************************/}// 点击按钮所实现的方法public void actionPerformed(ActionEvent e){useVoid();}public void useVoid(){// 1.获取文本框中的内容String text = jtf.getText();text = "服务端对客户端说:" + text;// 自己显示jta.append(text + "\n");// 2.发送try{// 4.发送bw.write(text);bw.newLine(); // 换行bw.flush();  // 刷新// 5.清空文本框jtf.setText("");}catch (IOException e1){e1.printStackTrace();}}/*public void KeyPressed(KeyEvent e){//回车键System.out.println("按钮数字");}public void KeyTyped(KeyEvent e){}public void KeyReleased(KeyEvent e){}*///行为
}

实现客户端的对话框来获取服务器端的ip地址和端口号进行链接:


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class QqFu extends JFrame implements ActionListener{public static void main(String[] args){new QqFu();}// 说明:一个类需要页面的显示,则那个类要继承JFrame。// 属性// 文本域private JTextArea jta;// 滚动条private JScrollPane jsp;// 面板里面是文本框和按钮private JPanel jp;private JTextField jtf;private JButton jb ;BufferedWriter bw = null;// 构造器public QqFu(){// 初始化上面的属性jta = new JTextArea();// 将文本域添加到滚动条中jsp = new JScrollPane(jta);jp = new JPanel();jtf =new JTextField(15);jb = new JButton("发送");// 把按钮和文本框添加到面板中jp.add(jtf);jp.add(jb);// 把滚动条和面板添加到JFrame中去this.add(jsp,BorderLayout.CENTER); //这个设置在中间this.add(jp,BorderLayout.SOUTH); //南this.setTitle("qq聊天客户端");  //获取用户的昵称this.setSize(500,500);this.setLocation(200, 200);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);jb.addActionListener(this);// 回车点击事件jtf.addKeyListener(new KeyAdapter() {public void keyTyped(KeyEvent e) {if((char)e.getKeyChar()==KeyEvent.VK_ENTER) {useVoid01();}}});try{/*******客户端 TCP协议*********/// 1.创建一个客户端的套接字(尝试连接)Socket socket = new Socket("127.0.0.1",8888);// 2.获取socket通道的输入流BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 3bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));String line = null;while((line = br.readLine()) !=null){jta.append(line + "\n");}// 3. 获取输出流// 4.关闭流socket.close();/******************************/}catch(Exception e){e.printStackTrace();}}public void actionPerformed(ActionEvent e){useVoid01();}public void useVoid01(){// 1.获取文本框中需要发送的内容String text = jtf.getText();// 2. 拼接内容text = "客户端对服务端说:" + text;// 3.自己显示jta.append(text + "\n");try{// 4.发送bw.write(text);bw.newLine(); // 换行bw.flush();  // 刷新// 5.清空jtf.setText("");}catch(IOException e1){e1.printStackTrace();}}//行为
}

必须先启动服务端再启动客户端才可,如果是两台电脑的情况下,只需要获得其中一个电脑的ip进行服务器启动,另一个进行链接即可。就可实现实时对话

效果展示:

UDP群聊服务器端:

import java.io.*;  
import java.net.*;  
import java.util.HashMap;  
import java.util.Map;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.ThreadPoolExecutor;  
import javax.swing.*;
import java.awt.*;public class UDPServer extends JFrame{      private JTextArea m_display=new JTextArea();private ServerSocket serverSocket;  /** * 创建线程池来管理客户端的连接线程 * 避免系统资源过度浪费 */  private ExecutorService exec;  // 存放客户端之间私聊的信息  private Map<String,PrintWriter> storeInfo;  public UDPServer() {  super("聊天程序服务器端");Container c=getContentPane();c.add(new JScrollPane(m_display),BorderLayout.CENTER);try {  serverSocket = new ServerSocket(6666);  storeInfo = new HashMap<String, PrintWriter>();  exec = Executors.newCachedThreadPool();  } catch (Exception e) {  e.printStackTrace();  }  }  // 将客户端的信息以Map形式存入集合中  private void putIn(String key,PrintWriter value) {  synchronized(this) {  storeInfo.put(key, value);  }  }  // 将给定的输出流从共享集合中删除  private synchronized void remove(String  key) {  storeInfo.remove(key);  m_display.append("当前在线人数为:"+ storeInfo.size());//for(String name: storeInfo.key)}  // 将给定的消息转发给所有客户端  private synchronized void sendToAll(String message) {  for(PrintWriter out: storeInfo.values()) {  out.println(message);  // m_display.append("已经发送了");}  }  // 将给定的消息转发给私聊的客户端  private synchronized void sendToSomeone(String name,String message) {  PrintWriter pw = storeInfo.get(name); //将对应客户端的聊天信息取出作为私聊内容发送出去  if(pw != null) pw.println("私聊:     "+message);   }  public void start() {  try {  m_display.setVisible(true);//m_display.append("mayanshuo");while(true) { m_display.append("等待客户端连接... ... \n"); Socket socket = serverSocket.accept();  // 获取客户端的ip地址  InetAddress address = socket.getInetAddress();  m_display.append("客户端:“" + address.getHostAddress() + "”连接成功! ");  /* * 启动一个线程,由线程来处理客户端的请求,这样可以再次监听 * 下一个客户端的连接 */  exec.execute(new ListenrClient(socket)); //通过线程池来分配线程  }  } catch(Exception e) {  e.printStackTrace();  }  }  /** * 该线程体用来处理给定的某一个客户端的消息,循环接收客户端发送 * 的每一个字符串,并输出到控制台 */  class ListenrClient implements Runnable {  private Socket socket;  private String name;  public ListenrClient(Socket socket) {  this.socket = socket;  }  // 创建内部类来获取昵称  private String getName() throws Exception {  try {  //服务端的输入流读取客户端发送来的昵称输出流  BufferedReader bReader = new BufferedReader(  new InputStreamReader(socket.getInputStream(), "UTF-8"));  //服务端将昵称验证结果通过自身的输出流发送给客户端  PrintWriter ipw = new PrintWriter(  new OutputStreamWriter(socket.getOutputStream(), "UTF-8"),true);  //读取客户端发来的昵称  while(true) {  String nameString = bReader.readLine();  if ((nameString.trim().length() == 0) || storeInfo.containsKey(nameString)) {  ipw.println("FAIL");  } else {  ipw.println("OK");  return nameString;  }  }  } catch(Exception e) {  throw e;  }  }  @Override         public void run() {  try {  /* * 通过服务器端的socket分配给每一个 * 用来将消息发送给客户端 */  PrintWriter pw = new PrintWriter(  new OutputStreamWriter(socket.getOutputStream(), "UTF-8"), true);  /* * 将客户昵称和其所说的内容存入共享集合HashMap中 */  name = getName();  putIn(name, pw);  Thread.sleep(100);  // 服务端通知所有客户端,某用户上线  sendToAll("*系统消息* “" + name + "”已上线");  /* * 通过客户端的Socket获取输入流 * 读取客户端发送来的信息 */  BufferedReader bReader = new BufferedReader(  new InputStreamReader(socket.getInputStream(), "UTF-8"));  String msgString = null;  while((msgString = bReader.readLine()) != null) {  // 检验是否为私聊(格式:@昵称:内容)  if(msgString.startsWith("@")) {  int index = msgString.indexOf(":");  if(index >= 0) {  //获取昵称  String theName = msgString.substring(1, index);  String info = msgString.substring(index+1, msgString.length());  info =  name + ":"+ info;  //将私聊信息发送出去  sendToSomeone(theName, info);sendToSomeone(name,info);continue;  }  }  // 遍历所有输出流,将该客户端发送的信息转发给所有客户端  m_display.append(name+":"+ msgString+"\n");  sendToAll(name+":"+ msgString);  }     } catch (Exception e) {  // e.printStackTrace();  } finally {  remove(name);  // 通知所有客户端,某某客户已经下线  sendToAll("*系统消息* "+name + "已经下线了。\n");  if(socket!=null) {  try {  socket.close();  } catch(IOException e) {  e.printStackTrace();  }  }     }  }  }  public static void main(String[] args) {  UDPServer server = new UDPServer();server.setSize(400,400);server.setVisible(true);server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);server.start();  }  
}  

UDP客户端:


import java.io.*;  
import java.net.*;  
import java.util.Scanner;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.ThreadPoolExecutor;  
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;public class UDPClient extends JFrame {  private JTextField m_enter=new JTextField();private JTextArea m_display=new JTextArea();private int m_count=0;private static  Socket clientSocket;  //private ExecutorService exec = Executors.newCachedThreadPool(); private BufferedReader br;private PrintWriter pw;public UDPClient() {super("聊天程序客户端");Container c=getContentPane();//m_enter.setSize(100,99);//m_display.setSize(200,100);m_enter.setVisible(true);m_display.setVisible(true);m_enter.requestFocusInWindow();     //转移输入焦点到输入区域//将光标放置在文本区域的尾部m_display.setCaretPosition(m_display.getText().length());c.add(m_enter,BorderLayout.SOUTH);c.add(new JScrollPane(m_display),BorderLayout.CENTER);  // this.add(panel);// this.setContentPane(jp);}  public static void main(String[] args) throws Exception {  UDPClient client = new UDPClient();client.setVisible(true);client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);client.setSize(470,708);client.start();  }  public void start() {  try {  m_display.append("请创建用户名:");clientSocket=new Socket("localhost",6666);BufferedReader br = new BufferedReader(  new InputStreamReader(clientSocket.getInputStream(), "UTF-8")); PrintWriter pw = new PrintWriter(  new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"), true); //ListenrServser l=new ListenrServser();m_enter.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent event){try{String s=event.getActionCommand();m_enter.setText("");if(m_count==0){pw.println(s);m_display.append("\n'"+s+"'"+"昵称设置成功。\n");}else{pw.println(s);}m_count++;}catch(Exception e){e.printStackTrace();}}});String msgString;while((msgString = br.readLine())!= null) {  m_display.append(msgString+"\n");  }  } catch(Exception e) {  e.printStackTrace();  } finally {  if (clientSocket !=null) {  try {  clientSocket.close();  } catch(IOException e) {  e.printStackTrace();  }  }  }  }  }

运行结果:

1、这里是服务器端,显示当前连接人数,以及公聊信息:

自由创建对象来实现群聊

效果如图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/257701.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++_命名空间(namespace)

目录 1、namespace的重要性 2、 namespace的定义及作用 2.1 作用域限定符 3、命名空间域与全局域的关系 4、命名空间的嵌套 5、展开命名空间的方法 5.1 特定展开 5.1 部分展开 5.2 全部展开 结语&#xff1a; 前言&#xff1a; C作为c语言的“升级版”&#xff0c;其在…

Constraining Async Clock Domain Crossing

Constraining Async Clock Domain Crossing 我们在normal STA中只会去check 同步clock之间的timing,但是design中往往会存在很多CDC paths,这些paths需要被正确约束才能保证design function正确,那么怎么去约束这些CDC paths呢? 以下面的design为例,如下图所示 这里clk…

Linux查看openSSL版本

命令&#xff1a;openssl version

RHEL8_Linux计划任务

本章主要介绍如何创建计划任务 使用 at 创建计划任务使用 crontab 创建计划任务 有时需要在某个指定的时间执行一个操作&#xff0c;此时就要使用计划任务了。计划任务有两种&#xff1a;一个是at计划任务&#xff0c;另一个是 crontab计划任务。 下面我们分别来看这两种计划任…

经纬恒润以太网网关,智能时代网络通关

汽车产业新四化步伐持续加速&#xff0c;智能网联逐渐成为整车标配&#xff0c;随着近年来相关政策频出以及对网联需求和功能的深度挖掘与发展&#xff0c;中国本土市场及本土供应商在这场新浪潮中逐渐走向C位。经纬恒润深耕智能网联领域多年&#xff0c;先后推出四代网关产品&…

用Rust刷LeetCode之66 加一

66. 加一[1] 难度: 简单 func plusOne(digits []int) []int { length : len(digits) // 从最低位开始遍历&#xff0c;逐位加一 for i : length - 1; i > 0; i-- { if digits[i] < 9 { digits[i] return digits } d…

文件重命名的最佳实践:如何批量处理文件,告别手动操作

在日常生活和工作中&#xff0c;经常要处理大量的文件&#xff0c;其中最频繁的操作之一就是给文件重命名。如果还在手动一个一个地重命名文件&#xff0c;那么就OUT了&#xff01;文件重命名无非是修改文件名中的某些字符或者顺序&#xff0c;以实现文件名的统一或者便于管理。…

大数据技术4:Lambda和Kappa架构区别

前言&#xff1a;在大数据处理领域&#xff0c;两种突出的数据架构已成为处理大量数据的流行选择&#xff1a;Lambda 架构和 Kappa 架构。这些架构为实时处理和批处理提供了强大的技术解决方案&#xff0c;使组织能够从其数据中获得有价值的见解。随着互联网时代来临&#xff0…

各大厂商证书申请遇到的问题

证书作用&#xff1a; 确保数据传输过程中不被篡改、拦截 遭受中间件攻击、确保数据完整性、保密性 申请方式&#xff1a; 文件验证、cname验证&#xff08;需要在域名平台上添加cname记录&#xff09; 本次采用文本验证 添加需要申请的域名 将tx生成的txt文件放在 IIS站点…

1 接口测试介绍

在软件测试工作中&#xff0c;接口测试是必不可少的。接口测试一般是发生在单元测试之后&#xff0c;系统测试之前。当开发人员输出API文档后&#xff0c;测试人员就可以开始编写接口测试用例了。接口测试可以让测试人员更早的介入&#xff0c;不需要等待前后端联调完成才开始测…

常用API(一)

API(全称 Application Programming Interface&#xff1a;应用程序编程接口) 就是别人写好的一些程序&#xff0c;给我们直接拿去调用即可解决问题的。 包 什么是包&#xff1f; 包是用来分门别类的管理各种不同程序的&#xff0c;类似于文件夹&#xff0c;建包有利于程序的管…

HCIP —— BGP 基础 (上)

BGP --- 边界网关协议 &#xff08;路径矢量协议&#xff09; IGP --- 内部网关协议 --- OSPF RIP ISIS EGP --- 外部网关协议 --- EGP BGP AS --- 自治系统 由单一的组织或者机构独立维护的网络设备以及网络资源的集合。 因 网络范围太大 需 自治 。 为区分不同的AS&#…