Socket编程与应用开发---- 数据采集的设计与实现(TCP)

​​​​​​

代码

Server:
#include 
#include 
#pragma comment(lib, "WS2_32")	// 链接到WS2_32.lib
#include 
#include //随机数头文件
 
    这是两个函数!一个是srand函数!这是在调用rand    ()这个函数之前使用的! rand()是一个产生随机数的函数!而srand是一个设置随机数种子的函数! 通常这两个函数是一起使用的!来完成产生随机数的功能!  而time(NULL)这个函数的返回值是作为srand函数的参数的!意思是以现在的系统时间作为随机数的种子来产生随机数!至于NULL这个参数。只有设置成NULL才能获得系统的时间!
 
生成随机数据,模拟采集的设备信息
int Rand()  
 {   srand(time(NULL));
	int j ;	
	j = rand()%1015448481651 ;
	return j;	
}
char buff[1000]={0};
此函数用来生成模拟设备信息的函数
char *creat()                          
{ 
   int num=Rand();                      //将生成的随机数,传给sum
   char *translate=(char *)malloc(1000);//向系统申请一个堆空间,malloc的返回值类型是void*,需要用(char*)来强转类型以和等号左边匹配
   memset(translate,0,1000);            //清空这个区域
   char m[100]={0};
   sprintf(m,"%d",num);                //把格式化的数据写入某个字符串缓冲区
   memcpy(buff,m,sizeof(buff));
   printf("采集到的数据%s\n\n", buff);//以字符串形式打印输出变量str后光标换行
   return(buff);
}
void main()
{	
    printf("TCP服务器(采集点)\n\n\n\n"); 
	SOCKET sock1,sock2;
	WSADATA wsadata;
	struct sockaddr_in sai;
	int count;
	//地址初始化
	sai.sin_family = AF_INET;
	sai.sin_port = htons(4777);
	sai.sin_addr.s_addr = inet_addr("127.0.0.1");
	//连接
	printf("================等待客户端启动==================\n");
	printf("\n\n\n\n");
	WSAStartup(MAKEWORD(1,1),&wsadata);//加载套接字库和版本协商
	sock1=socket(AF_INET,SOCK_STREAM,0);
	bind(sock1,(struct sockaddr*)&sai,sizeof(sai));
	listen(sock1,2);
	count=sizeof(sai);
	sock2=accept(sock1,(struct sockaddr*)&sai,&count);//接收并保存客户端信息
	printf("=============已与客户端连接========================\n");
	for( int i=0;i<5;i++)
	{
	    *creat();
		send(sock2,buff,sizeof(buff),0);
		Sleep(2000);
	}
	closesocket(sock1);
	closesocket(sock2);
	WSACleanup();
    printf("\n=====================关闭========================\n"); 
}


Client:
//TCP客户端
#pragma comment(lib,"WS2_32")
#include"winsock.h"
#include"stdio.h"
#include 
    声明IP头数据结构,ICMP协议是IP层的一个协议,但是由于差错报告在发送给报文源发方时可能也要经过若干子网,因此牵涉到路由选择等问题,所以ICMP报文需通过IP协议来发送。
//ICMP数据报的数据发送前需要两级封装:首先添加ICMP报头形成ICMP报文,再添加IP报头形成IP数据报
typedef struct _IPHeader  // 20字节的IP头
{
    UCHAR     iphVerLen;      // 版本号和头长度(各占4位)
    UCHAR     ipTOS;          // 服务类型 
    USHORT    ipLength;       // 封包总长度,即整个IP报的长度
    USHORT    ipID;	          // 封包标识,惟一标识发送的每一个数据报
    USHORT    ipFlags;	      // 标志和片偏移
    UCHAR     ipTTL;	      // 生存时间,就是TTL,指出IP数据报能在网络上停留的最长时间,其值由发送方设定,并在经过路由的每一个节点时减一,当该值为0时,数据报将被丢弃
    UCHAR     ipProtocol;     // 协议,可能是TCP、UDP、ICMP等
    USHORT    ipChecksum;     // 校验和
    ULONG     ipSource;       // 源IP地址
    ULONG     ipDestination;  // 目标IP地址
} IPHeader, *PIPHeader; 

//ICMP头数据结构
typedef struct icmp_hdr
{
    unsigned char   icmp_type;		// 消息类型
    unsigned char   icmp_code;		// 代码
    unsigned short  icmp_checksum;	// 校验和
    unsigned short  icmp_id; // 用来惟一标识此请求的ID号,通常设置为进程ID
    unsigned short  icmp_sequence;	// 序号
    unsigned long   icmp_timestamp; // 数据传输时间
}ICMP_HDR, *PICMP_HDR;

//ICMP回送请求的数据结构
typedef struct _EchoRequest
{
	ICMP_HDR icmphdr;
	char cData[32];
}ECHOREQUEST,*PECHOREQUEST; 

//ICMP回送应答的数据结构
#define REQ_DATASIZE 32
typedef struct _EchoReply
{
	IPHeader iphdr;
	ECHOREQUEST echoRequest;
}ECHOREPLAY,*PECHOREPLAY; 
// 校验和的计算
// 以16位的字为单位将缓冲区的内容相加,如果缓冲区长度为奇数,
// 则再加上一个字节。它们的和存入一个32位的双字中
//USHORT checksum(USHORT* buff, int size);
USHORT checksum(USHORT* buff, int size)
{	u_long cksum = 0;
	while(size>1)                        // 将数据以字为单位累加到cksum 中
    {
		cksum=cksum+ *buff;  
        buff= buff +1;
		size= size- sizeof(USHORT); //等价于size=size-2;
	}  
	if(size==1)                    // 共有奇数个字节将最后一个字节扩展为字,再累加
      {                      
		USHORT u=0;
		u=(USHORT)(*(UCHAR*)buff);
		cksum = cksum +u;	
      }
	// 校验位计算
	//高16位和低16位相加
	cksum = (cksum >> 16) + (cksum & 0x0000ffff); 
	cksum = cksum+(cksum >> 16);//本身再加上当前的高16位 
    u_short  answer=(u_short)(~cksum);//取反并转换为16位数
	return (answer);
}
void Sock();
int getmax(int backTime[],int n) // 计算最大时间
{
	int nmax = backTime[0];
	for(int i=0;i backTime[i])
		{
			nmax = backTime[i];
		}
	}
	return nmax;
}

int getavg(int backTime[],int n) // 计算平均值
{
	int nmax = 0;
	for(int i=0;i

​​​​​​程序运行

客户端先ping5次

Socket编程与应用开发---- 数据采集的设计与实现(TCP)_第1张图片

平后,客户端确定,是否接受服务端的数据

Socket编程与应用开发---- 数据采集的设计与实现(TCP)_第2张图片

确定接受后,客户端显示接受到的数据

Socket编程与应用开发---- 数据采集的设计与实现(TCP)_第3张图片

 

 

 

 

你可能感兴趣的:(Socket编程与应用开发---- 数据采集的设计与实现(TCP))