局域网实时聊天系统(JAVA)--利用Sock

摘要:本文基于传输层(TCP协议)和网络层(IP协议)利用Java Socket(套接字)来实现双机通信,它采用客户/服务器通信机制,使客户端和服务器端通过Socket接口在网络上实现连接和数据交换。通过本文对Socket通信的实现简单的分析和讲解,让大家对Socket的原理有一个较清晰的认识。

关键词:JAVA通信、套接字、SocketServer类、客户机/服务器模式

2程序功能的实现

2.1程序的结构

 

本程序共有四个类:LoginWindow登录窗口类、MainActivity主类、chatServer服务器类、chatClinet客户端类,均放在一个LANChatSoftware文件中,如图所示:  


 

2.3主界面的开发

主界面主要有1个label标签和2个button按钮,实现打开服务器端,和客户端窗体。

 

2.4服务器端的开发

 

(1)服务器端实现对主机某个端口不断监听,并不断接受客户端的连接请求,当受到连接后打印客户的的信息并向客户端完成一次服务。

(2)使用readUTF方法的DataInputStream处理流提供的方法,功能为读取满足UTF格式的字符串。并使用writeUTF方法为DataOutputStream处理流提供的方法,功能为写出满足UTF 格式的字符。一般在网络中发生消息都在发送端用writeUTF方法写,在接收端使用readUTF方法读取,这样程序的兼容性强,不容易受到乱码。

 

2.5客户端的开发

(1)客户端用于对某个固定IP的服务器进行连接,接着向服务器发送一条消息,最后接受服务器的返回消息并打印。

(2)为了与服务器对应,发送消息还要使用DataInputStream的writeUTF方法。同时应该注意的两边的首发顺序是互逆的,服务器现售后发,客户端先发后收。

 

3程序的具体代码

3.1登陆界面

/*
 * 登录界面
 */

 

public  class LoginWindow extends JDialog implements ActionListener{

 //自定义5个面板
 JPanel p1=new JPanel();
 JPanel p2=new JPanel();
 JPanel p3=new JPanel();
 JPanel p4=new JPanel();
 JPanel p5=new JPanel();
 int i=0;//记录密码输错的次数
 JTextField txtUserName=new JTextField(15);// 用户名文本框
 JPasswordField txtPassword=new JPasswordField(15);// 密码域文本框
 JButton ok=new JButton("确定");// 确定按钮
 JButton cancel=new JButton("取消");//取消按钮
// LoginWindow方法
 public LoginWindow(){
  Container contentPane=this.getContentPane();//获取内容面板
  contentPane.setLayout(new GridLayout(5,1));//设置5行1列的网格布局
  p2.add(new JLabel("用户名:"));
  p2.add(txtUserName);
  p3.add(new JLabel("密码:"));
  p3.add(txtPassword);
  p4.add(ok);
  p4.add(cancel);
//  添加按钮监听
  ok.addActionListener(this);
  cancel.addActionListener(this);
  contentPane.add(p1);
  contentPane.add(p2);
  contentPane.add(p3);
  contentPane.add(p4);
  contentPane.add(p5);
  
  setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
  setSize(350, 250);
  Dimension screen=Toolkit.getDefaultToolkit().getScreenSize();
  setLocation((screen.width-300)/2,(screen.height-220)/2);
  setTitle("聊天软件(by:春天的故事原创)-登陆窗口");
  setResizable(false);
  setVisible(true);
 }
 

 @Override
 public void actionPerformed(ActionEvent e) {
  String password=new String(txtPassword.getPassword());
  //String
  if(e.getSource()==ok||e.getSource()==txtPassword){
   if (txtUserName.getText().trim().equals("gyc")&&password.equals("1")) {
    this.dispose();//关闭窗口
    new MainActivity();//调出MainActivity聊天主窗口
   }
   else {
    if(++i>=3){//三次密码输入错误关闭窗口退出程序
     this.dispose();
     System.exit(0);
    }
    JOptionPane.showMessageDialog(null, "用户名或密码错误!联系作者获得用户密码");
    txtUserName.requestFocus();//设置焦点
    txtUserName.setSelectionStart(0);//设置选中文本开始位置
    txtUserName.setSelectionEnd(txtUserName.getText().length());
   }
  }
  
  else if(e.getSource()==cancel){//单机取消按钮
   this.dispose();
   System.exit(0);
  }
  
  else if (e.getSource()==txtPassword) {
   txtPassword.requestFocus();//密文
  }
 }

 public static void main(String [] args){
  new LoginWindow();//实例化LoginWindow
 }
}

3.2主窗口

/*
 * 程序的主窗口
 * 打开客户端,服务器
 */

 

public class MainActivity extends JFrame implements ActionListener{
 private static final long serialVersionUID = 1L;
 JPanel p1=new JPanel();
 JPanel p2=new JPanel();
 JPanel p3=new JPanel();
 Button btn1=new  Button("打开服务器");
 Button btn2=new  Button("打开客户端");
 Button ok=new Button("确定");
 Label lab1=new Label("先开启服务器再开启客户端");
 Dialog dia;

public MainActivity(){
 super("聊天软件(by:春天的故事原创)-主界面");
 Container con=getContentPane();//获得内容窗格
 con.setLayout(new GridLayout(4,1));//网格布局
 p1.add(lab1);
 p2.add(btn1);
 p3.add(btn2);
 con.add(p1);
 con.add(p2);
 con.add(p3);
 btn1.addActionListener(this);
 btn2.addActionListener(this);
 setSize(350, 250);
 Dimension screen=Toolkit.getDefaultToolkit().getScreenSize();
 setLocation((screen.width-300)/2,(screen.height-220)/2);
 setTitle("聊天软件(by:春天的故事原创)-登陆窗口");
 setResizable(false);
 setVisible(true);
 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
@Override
public void actionPerformed(ActionEvent e) {
 // TODO Auto-generated method stub
  if (e.getSource()==btn1) {
  new chatServer();
 }else if (e.getSource()==btn2) {
  this.dispose();//关闭窗口
   new chatClient();
 }
}

public static void main(String[] args) {
 MainActivity a=new MainActivity();
 a.setSize(280,180);
 a.setLocation(350,300);
}
}

3.3服务器端的实现 

服务器端用一个类chatServer来实现,创建一个ServerSocket类的对象,实现对端口6500的不断监听,直到受到客户端的信息。

 

 

服务器端

/*

 * 该类主方法将接收数据的部分放在线程中,他始终在后台运行,一旦对方发来数据,就立即显示在界面上

 */

JTextArea showArea;
JTextField msgText;
JFrame mainJframe;
JButton sentBtn;
JScrollPane JSPane;
JPanel pane;
DataInputStream inFromClient;
DataOutputStream outTOClient;

public chatServer() {
 // TODO Auto-generated constructor stub
// 设置界面
 mainJframe=new JFrame("聊天软件(by:春天的故事原创)-服务器端");
 Container con = mainJframe.getContentPane();
 showArea=new JTextArea();//创建文本域
 showArea.setEditable(false);
 showArea.setLineWrap(true);
 JSPane=new JScrollPane(showArea);//创建滚动面板
 msgText=new JTextField();//创建文本框
 msgText.setColumns(30);
 msgText.addActionListener(this);
 sentBtn=new JButton("发送");//发送按钮
 sentBtn.addActionListener(this);
 pane=new JPanel();
 pane.setLayout(new FlowLayout());//组件布局
 pane.add(msgText);
 pane.add(sentBtn);
 con.add(JSPane,BorderLayout.CENTER);
 con.add(pane,BorderLayout.SOUTH);
 mainJframe.setSize(500,400);
 mainJframe.setVisible(true);
 mainJframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
// 通信
 try {
  InetAddress client=InetAddress.getLocalHost();
  ServerSocket serverSocket = new ServerSocket(5500);//创建服务套接字
  showArea.append("您的连接IP地址是:"+client.getHostAddress()+"\n\n正在等待连接请求...\n");
  Socket connectTOClient = serverSocket.accept();//监听客户端连接
  inFromClient = new DataInputStream(connectTOClient.getInputStream());
  outTOClient = new DataOutputStream(connectTOClient.getOutputStream());
  Thread thread=new Thread((Runnable) this);//启动线程在后台来接收对方的消息
  thread.setPriority(Thread.MIN_PRIORITY);
  thread.start();
 } catch (Exception e) {
  // TODO: handle exception
  showArea.append("抱歉,服务器创建不成功!请联系作者!\n");
  msgText.setEditable(false);
  sentBtn.setEnabled(false);
 }
}
@Override
 public void actionPerformed(ActionEvent e) {//响应按钮事件,发送消息给对方
  // TODO Auto-generated method stub
  String s=msgText.getText();
  if (s.length()>0) {
   try {
    outTOClient.writeUTF(s);
    outTOClient.flush();
    showArea.append("            我说:"+msgText.getText()+"\n");
    msgText.setText(null);
   } catch (Exception e1) {
    // TODO: handle exception
    showArea.append("你的消息是:“"+msgText.getText()+"”未能发出去\n");
   }
  }
 }

public void run() {//本线程负责将客户端传来的消息显示在对话区域
 // TODO Auto-generated method stub
 try {
 while (true) {
 showArea.append("对方说:"+inFromClient.readUTF()+"\n");
 Thread.sleep(1000);
 }
} catch (IOException e1) {}
 catch(InterruptedException e){}
} }

3.4客户端的实现

客户端

/*

 * 我们还要创建一个和服务器 对等的客户端页面来实现和服务器端相似的功能

 */

public class chatClient implements ActionListener,Runnable{
JTextArea showArea;
JTextField msgText;
JFrame mainJframe;
JButton sentBtn;
JScrollPane JSPane;
JPanel pane;
Container con;
Thread thread=null;
Socket connectTOServer;
DataInputStream inFromServer;
DataOutputStream outTOServer;

public chatClient() {
 // TODO Auto-generated constructor stub
 mainJframe=new JFrame("聊天软件(by:春天的故事原创)-客户端");
 con=mainJframe.getContentPane();
 showArea=new JTextArea();
 showArea.setEditable(false);
 showArea.setLineWrap(true);
 JSPane=new JScrollPane(showArea);
 msgText=new JTextField();
 msgText.setColumns(30);
 msgText.addActionListener(this);
 sentBtn=new JButton("发送");
 sentBtn.addActionListener(this);
 pane=new JPanel();
 pane.setLayout(new FlowLayout());
 pane.add(msgText);
 pane.add(sentBtn);
 con.add(JSPane,BorderLayout.CENTER);
 con.add(pane,BorderLayout.SOUTH);
 mainJframe.setSize(500,400);
 mainJframe.setVisible(true);
 mainJframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 Socket client=new Socket();
// 通信
 try {
  InetAddress client1=InetAddress.getLocalHost();
//  创建套接字连接服务器
  connectTOServer = new Socket("localhost",5500);
  inFromServer = new DataInputStream(connectTOServer.getInputStream());
  outTOServer = new DataOutputStream(connectTOServer.getOutputStream());
  showArea.append("服务器"+client1.getHostAddress() +"\n\n连接成功,开始通信\n");
  thread=new Thread(this);//创建线程在后台处理对方的消息
  thread.setPriority(Thread.MIN_PRIORITY);
  thread.start();
 } catch (Exception e) {
  // TODO: handle exception
  showArea.append("对不起,没能找到服务器\n");
  //文本框,发送按钮不可用
  msgText.setEditable(false);
  sentBtn.setEnabled(false);
 }
}
@Override
 public void actionPerformed(ActionEvent e) {//按钮响应事件,发送消息给对方
  // TODO Auto-generated method stub
  String s=msgText.getText();
  if (s.length()>0) {
   try {
    outTOServer.writeUTF(s);
    outTOServer.flush();
    showArea.append("            我说:"+msgText.getText()+"\n");
    msgText.setText(null);
   } catch (Exception e1) {
    // TODO: handle exception
    showArea.append("你的消息是:“"+msgText.getText()+"”未能发出去\n");
   }
  }
 }

public void run() {//本线程负责将服务器传来的信息显示在对话区域
 // TODO Auto-generated method stub

 try {
 while (true) {
 showArea.append("对方说:"+inFromServer.readUTF()+"\n");
 Thread.sleep(1000);
 }
} catch (IOException e1) {
 // TODO: handle exception
}catch(InterruptedException e){}
}
}

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
抱歉,我是一个语言模型AI,并不能直接提供代码。不过,可以给您一些思路和建议。 首先,您需要确定使用的Wi-Fi模块和相应的通信协议。常见的Wi-Fi模块有ESP8266、ESP32、Arduino Wi-Fi Shield等,在通信协议方面可以选择TCP、UDP、HTTP等。 在c语言中,可以使用Socket编程实现Wi-Fi模块之间的通信。您需要使用socket函数建立客户端和服务器之间的连接,并使用send和recv函数发送和接收数据。 以下是一个简单的使用TCP协议实现Wi-Fi模块之间通信的例子: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main() { int sockfd; struct sockaddr_in server_addr; char buffer[1024]; // 创建socket sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { printf("Create socket failed!\n"); exit(1); } // 设置server地址 bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8888); server_addr.sin_addr.s_addr = inet_addr("192.168.1.100"); // 建立连接 if (connect(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) { printf("Connect failed!\n"); exit(1); } // 发送数据 strcpy(buffer, "Hello, Wi-Fi module!"); send(sockfd, buffer, strlen(buffer), 0); // 接收数据 recv(sockfd, buffer, 1024, 0); printf("Received message: %s\n", buffer); // 关闭socket close(sockfd); return 0; } ``` 说明: - 使用socket函数创建了一个TCP客户端,连接到IP地址为192.168.1.100,端口号为8888的服务器。 - 使用send函数向服务器发送了一条消息。 - 使用recv函数接收服务器返回的消息。 - 最后关闭了socket。 当然,具体的实现还要根据您的具体要求和Wi-Fi模块的特性来调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

花北城

你的鼓励是我最大的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值