基于UDP通信的虚拟红外测距仪

基于UDP通信的虚拟红外测距仪

分为两个部分
sensor:负责接收初始化信息并根据不同指令做出操作
以生成随机数的方式模拟时间测量
代码部分:

// Sensor_UDP.cpp: 定义控制台应用程序的入口点。
#include <winsock2.h>
#pragma comment (lib, "ws2_32.lib")   // 使用WinSock2.2实现网络通信所需文件
#define _WINSOCK_DEPRECATED_NO_WARNINGS 
#include <time.h>
#include <stdio.h>
#include <math.h>
#include<time.h>
#define BUFF_SIZE 64
double generate();
char response[BUFF_SIZE];
int main()
{ //创建接收与发送缓冲区
 char recvbuff[BUFF_SIZE];
 char sendbuff[BUFF_SIZE];
 WSADATA wsaData;
 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
  printf("dll初始化失败");
}
 //创建套接字
 SOCKET hServer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 if (hServer == INVALID_SOCKET) {
  printf("socket failed \n");
  return 0;
 }
 //创建服务器端地址并绑定端口号的IP地址
 sockaddr_in addrServer;
 addrServer.sin_family = AF_INET;
 addrServer.sin_port = htons(8889);
 addrServer.sin_addr.S_un.S_addr = INADDR_ANY;
 int nRet = bind(hServer, (sockaddr*)&addrServer, sizeof(addrServer));
 if (nRet == SOCKET_ERROR) {
  printf("socket bind failed\n");
  closesocket(hServer);
  WSACleanup();
  return 0;
 }
 //接收客户端请求
 SOCKADDR clntAddr;  //客户端地址信息
 int nSize = sizeof(SOCKADDR);
 //等待接收初始化命令
 while (1) {
  int strLen = recvfrom(hServer, recvbuff, BUFF_SIZE, 0, &clntAddr, &nSize);   //接收指令,并储存数据长度
  recvbuff[strLen] = '\0';        //防止出现乱码
  if (recvbuff != 0)
  {
   sendto(hServer, "1", strlen("1"), 0, &clntAddr, nSize);
   break;
  }
 }
 memset(recvbuff, 0, BUFF_SIZE); //重置缓冲区
 while (1) {
  int strLen = recvfrom(hServer, recvbuff, BUFF_SIZE, 0, &clntAddr, &nSize);   //接收指令,并储存数据长度
  recvbuff[strLen] = '\0';        //防止出现乱码
  if (strcmp(recvbuff, "read_mode") == 0)
  {
   //判断指令
   double timing = generate();       //产生模拟数据
   printf("单次距离读取指令\n");
   sprintf_s(response, sizeof(response), "%.6f", timing);    //double 转 字符串
   sendto(hServer, response, strlen(response), 0, &clntAddr, nSize);
  }
  else if (strcmp(recvbuff, "close") == 0)
  {
   printf("断开连接指令\n");
   sendto(hServer, "服务器已关闭\0", strlen("服务器已关闭\0"), 0, &clntAddr, nSize);
   break;
  }
  else
  {
   printf("指令输入有误\n");
   sendto(hServer, "指令输入有误\0", strlen("指令输入有误\0"), 0, &clntAddr, nSize);
   printf("错误指令:%s\n", recvbuff);
  }
  memset(recvbuff, 0, BUFF_SIZE); //重置缓冲区
  memset(sendbuff, 0, BUFF_SIZE); //重置缓冲区
 }
 //关闭套接字
 closesocket(hServer);
 WSACleanup();
 return 0;
}
double generate()
{    //产生模拟数据
 srand((unsigned)time(NULL));
 double timing = (rand() % 1000);//生成时间单位为微秒
 return timing;
}

workstation:负责发送初始化信息,并通过用户输入不同指令进行指挥sensor操作,并对传输数据进行转换、记录、回查、显示
代码部分

#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")  // 使用WinSock2.2实现网络通信所需文件
#include<stdlib.h>
#include<windows.h>
#include<iostream>
#include<stdio.h>
#include<string>
#include <Ws2tcpip.h>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define BUFF_SIZE 64  // 缓冲区大小
#define STORAGE_SIZE 10  //历史记录上限
#define Cspeed 3.0e8
#define ACCURACY 3
const int BUFFER_SIZE = 1024;
char buffer[BUFFER_SIZE];   //show函数中所用
char recvbuff[BUFF_SIZE] = { 0 };
char sendbuff[BUFF_SIZE] = { 0 };    // 创建接收与发送缓冲
double timing = 0.0;
double storage[STORAGE_SIZE] = { 0,0,0,0,0,0,0,0,0,0 };       //储存历史数据
int J = -1;    //指向最新数据
int K = 0;    //指向回查数据
//函数声明
int sensorInit(SOCKET ConnectSocket, sockaddr_in servAddr, int accuracy); //初始化 
double trans(double timing);     //把时间转换成距离并存储
double read_storage();     //阅读历史数据
void read_mode(SOCKET ConnectSocket);   //读取距离
void show(double storage[STORAGE_SIZE]);   //把历史数据转换成曲线
sockaddr serSockAddr;     //不断获取输入并发送到服务器,接收服务器数据
int addrLen = sizeof(serSockAddr);
int main()
{
 // WSADATA结构体主要包含了系统所支持的winsock版本
 WSADATA wsaData;
 // 初始化winsock 2.2
 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
 {
  printf("WSAStartup 无法初始化! ");
  return 0;
 }
 //创建连接到服务器的SOCKET对象
 SOCKET sClient;
 sClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 if (SOCKET_ERROR == sClient) {
  printf("socket failed !\n");
  return 0;
 }
 //创建服务器端地址
 sockaddr_in serverAddr;
 //创建服务器端地址
 sockaddr_in clientAddr;
 //设置服务器端地址,端口号,协议族
 serverAddr.sin_family = AF_INET;
 serverAddr.sin_port = htons(8889);
 serverAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
 // 传感器初始化
 int init_zet = sensorInit(sClient, serverAddr, ACCURACY);
 //char strC1[30] = "单次距离读取",strC2[30] = "读取历史数据",strC3[30] = "清除历史数据";
 printf("提示: \n read_mode:单次距离读取\n read_storage:读取历史数据\n clear_storage:清空历史数据\nclose:关闭服务端\n");
 while (1) {
  if (init_zet == 1)
  {
   printf("Input a command:"); //输入命令
   scanf_s("%s", sendbuff, BUFF_SIZE);
   if (strcmp(sendbuff, "read_storage") == 0)
   {
    printf("历史记录: %f\n", read_storage()); //读取历史记录
   }
   else if (strcmp(sendbuff, "clear_storage") == 0)
   {
    memset(storage, 0, STORAGE_SIZE);
   }
   else {
    sendto(sClient, sendbuff, strlen(sendbuff), 0, (struct sockaddr*) & serverAddr, sizeof(serverAddr)); //发送数据
   }
   if (strcmp(sendbuff, "read_mode") == 0)
   {
    read_mode(sClient);
   }
   if (strcmp(sendbuff, "close") == 0)
   {
    printf("服务端已关闭\n");
   }
   memset(recvbuff, 0, BUFF_SIZE);
   memset(sendbuff, 0, BUFF_SIZE); //重置缓冲区
  }
  else
  {
   printf("传感器初始化失败\n");
   Sleep(10000);
   break;
  }
 }
 closesocket(sClient);
 WSACleanup();   // 释放资源
 // 清除工作
 if (WSACleanup() == SOCKET_ERROR)
  printf("WSACleanup 出错! ");
 printf("\n\n");
 system("pause");
 return 0;
}
int sensorInit(SOCKET ConnectSocket, sockaddr_in servAddr, int accuracy)
//初始化:成功返回1,不成功返回0  
{
 int i = 0;
 sprintf_s(sendbuff, sizeof(sendbuff), "%d", accuracy);
 while (strcmp(recvbuff, "1") != 0)
 {
  sendto(ConnectSocket, sendbuff, strlen(sendbuff), 0, (struct sockaddr*) & servAddr, sizeof(servAddr));
  //发送初始化信息,并建立连接
  recvfrom(ConnectSocket, recvbuff, BUFF_SIZE, 0, &serSockAddr, &addrLen);             //接收初始化结果信息
  Sleep(1);   //延时1ms
  i++;
 }
 if (i > 10)           //等待10ms以上
 {
  return 0;      //初始化失败
 }
 else return 1;             //初始化成功
}
double read_storage()
{
 char recvdata[BUFF_SIZE];
 printf("回看记录数(范围:0-9):");
 scanf_s("%s", recvdata, sizeof(recvdata));
 K = (J - strtol(recvdata, NULL, 10) + STORAGE_SIZE) % STORAGE_SIZE;
 //求回看数
 return storage[K];
}
double trans(double timing)
{
 double distance = 0;
 distance = timing * Cspeed / 2;
 J = (J + 1) % STORAGE_SIZE;
 storage[J] = distance;
 printf("Message from server:%f\n", distance);
 return 0;
}
void read_mode(SOCKET ConnectSocket)
{
 recvfrom(ConnectSocket, recvbuff, BUFF_SIZE, 0, &serSockAddr, &addrLen);
 //接收数据
 timing = strtod(recvbuff, NULL) / 1000000;
 //把字符型数据转换成整形
 trans(timing); //转换并存储
}

workstation的show函数部分将在下篇文章中展示,包括dll封装及GUI设计也在以后推出,欢迎点赞收藏!
最终效果:
在这里插入图片描述

  • 15
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

生如昭诩

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

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

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

打赏作者

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

抵扣说明:

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

余额充值