使用系统API合成IPv6:

如果你的APP需要连接的服务器 只有IPv4地址,没有域名,可以用 getaddrinfo 来解决。下面的代码,将IPv4地址(如:192.0.2.1) 地址转换为IPv6地址(如:包含  64:ff9b::192.0.2.1  的struct sockaddr_in6 )

#include <sys/socket.h>#include <netdb.h>#include <arpa/inet.h>#include <err.h>uint8_t ipv4[4] = {192, 0, 2, 1};struct addrinfo hints, *res, *res0;int error, s;const char *cause = NULL;char ipv4_str_buf[INET_ADDRSTRLEN] = { 0 };const char *ipv4_str = inet_ntop(AF_INET, &ipv4, ipv4_str_buf, sizeof(ipv4_str_buf));memset(&hints, 0, sizeof(hints));hints.ai_family = PF_UNSPEC;hints.ai_socktype = SOCK_STREAM;hints.ai_flags = AI_DEFAULT;error = getaddrinfo(ipv4_str, "http", &hints, &res0);if (error) {errx(1, "%s", gai_strerror(error));/*NOTREACHED*/}s = -1;for (res = res0; res; res = res->ai_next) {s = socket(res->ai_family, res->ai_socktype,res->ai_protocol);if (s < 0) {cause = "socket";continue;}if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {cause = "connect";close(s);s = -1;continue;}break;  /* okay we got one */}if (s < 0) {err(1, "%s", cause);/*NOTREACHED*/}freeaddrinfo(res0);

==================

#import "LTSocket.h"

#import <netinet/in.h>

#import <unistd.h>

#include <netdb.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <arpa/inet.h>

#import "LTUserInfo.h"

#import "LTAerobicsWarningStatictics.h"

#import "LTSetAerobicsStatictics.h"

#import "LTPondAerobicsInfo.h"

#include <err.h>

#include <fcntl.h>

#include<sys/ioctl.h>

#define TIME_OUT_TIME 20//connect超时时间20秒

@interface LTSocket ()

@property (assign,nonatomic)        NSInteger   iFlyState;

@property(retain,nonatomic)          NSTimer     *heartbeatTimer;

@end

@implementation LTSocket

- (void)dealloc

{

self.m_pDelegeate =nil;

CFRelease(m_pSocket);

m_pSocket =nil;

[m_pInitThreadrelease];

m_pInitThread =nil;

[superdealloc];

}

- (id)init

{

self = [superinit];

if (self) {

[selfcreateConnect];//LTMainViewController创建的时候实例化socket,到这一步建立连接

从appdelegate接收的通知

[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(initSocket:)name:@"initSocket"object:nil];

//从溶氧控制页面接收的通知

[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(cancelSocket)name:@"cancelSocket"object:nil];

}

returnself;

}

//点击退出按钮后取消socket

-(void)cancelSocket{

CFSocketInvalidate(m_pSocket);

}

//锁屏后从appdelegate接收通知重新连接socket

-(void)initSocket:(NSNotification *)noti{

[selfcreateConnect];

}

- (void)stopInitThread

{

m_isReturn =YES;

[m_pInitThreadcancel];//线程取消

}

域名解析成IP

-(NSString*)hostNameToIP{

constchar *ptr;

char **pptr;

structhostent *hptr;//存储转换的结果

char str[32];

/* 取得命令后第一个参数,即要解析的域名或主机名 */

ptr ="www.hefeileran.cn";//60.173.247.137

/* 调用gethostbyname()。调用结果都存在hptr中 */

if( (hptr =gethostbyname(ptr) ) ==NULL )

{

printf("gethostbyname error for host:%s\n", ptr);

return0;/*如果调用gethostbyname发生错误,返回1 */

}

/* 将主机的规范名打出来 */

printf("official hostname:%s\n",hptr->h_name);

/* 主机可能有多个别名,将所有别名分别打出来 */

for(pptr = hptr->h_aliases; *pptr !=NULL; pptr++)

printf(" alias:%s\n",*pptr);

/* 根据地址类型,将地址打出来 */

switch(hptr->h_addrtype)

{

caseAF_INET:

caseAF_INET6:

pptr=hptr->h_addr_list;

/* 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数 */

for(;*pptr!=NULL;pptr++)

printf("address:%s\n",inet_ntop(hptr->h_addrtype, *pptr, str,sizeof(str)));

//********************

NSString *sss =nil;

for(pptr = hptr->h_addr_list; *pptr !=NULL; pptr++){

printf("h_addr_list:%s\n",*pptr);

constchar *s=inet_ntop(hptr->h_addrtype,*pptr,str,sizeof(str));

sss=[NSStringstringWithFormat:@"%s",s];

NSLog(@"-OC-%@-",sss);

}

return sss;

//********************

//            break;

//        default:

//            printf("unknown address type\n");

//            break;

}

return0;

}

//建立连接

- (void)createConnect

{

NSString  *ipv4_or_ipv6_strs=[selfhostNameToIP];//域名转换成IP地址

NSLog(@"-ddd-%@----",ipv4_or_ipv6_strs);

structaddrinfo hints, *res, *res0;

int error, s;

//    const char *cause = NULL;

constchar *ipv4_or_ipv6_str = [ipv4_or_ipv6_strscStringUsingEncoding:NSASCIIStringEncoding];//NSString转成char *类型

//    const char *ipv4_or_ipv6_str = "60.173.247.137";//or IPv6 address string is well /ip地址

//    const char *ipv4_or_ipv6_str = "http://www.hefeileran.cn";

NSUInteger port =9001;//port of connecting server/端口号

memset(&hints,0,sizeof(hints));//分配一个hints结构体,把它清零后填写需要的字段,再调用getaddrinfo,然后遍历一个链表逐个尝试每个返回地址。

hints.ai_family =PF_UNSPEC;

hints.ai_socktype =SOCK_STREAM;

hints.ai_flags =AI_DEFAULT;

int flags;

error = getaddrinfo(ipv4_or_ipv6_str,NULL, &hints, &res);//函数的返回值:成功返回0,失败返回非零的 sockets error code

if (error)//非零则失败

{

errx(1,"%s",gai_strerror(error));

/*NOTREACHED*/

}

s = -1;

for (res = res0; res; res = res->ai_next)

{

s = socket(res->ai_family,

res->ai_socktype,

res->ai_protocol);//返回值:非负描述符成功,返回一个新的套接字描述,出错返回-1

close(s);/很关键,释放占用的socket描述//

//socket 设置成非阻塞状态-------------很重要

flags = fcntl(s,F_GETFL,0);

fcntl(s,F_SETFL, flags |O_NONBLOCK);

//socket 设置成非阻塞状态-------------很重要

//

//socket上下文

CFSocketContext sockContext = {0,

self,

NULL,

NULL,

NULL};

//创建socket

m_pSocket =CFSocketCreate(kCFAllocatorDefault,

res->ai_family,//AF_UNSPEC不限,PF_INET,PF_INET6

res->ai_socktype,

res->ai_protocol,

kCFSocketConnectCallBack,

TCPClientConnectCallBack,  //连接后的回调函数

&sockContext

);

if (s <0)

{

//            cause = "socket";

continue;

}

switch(res->ai_addr->sa_family)//是IPV4还是IPV6

{

caseAF_INET://IPV4

{

structsockaddr_in *v4sa = (structsockaddr_in *)res->ai_addr;

v4sa->sin_port =htons(port);

CFDataRef address =CFDataCreate(kCFAllocatorDefault, (UInt8 *)&v4sa,sizeof(v4sa));

// 建立连接

CFSocketConnectToAddress(m_pSocket,

address,

-1    //超时

);

CFRunLoopRef cRunRef =CFRunLoopGetCurrent();

CFRunLoopSourceRef sourceRef =CFSocketCreateRunLoopSource(kCFAllocatorDefault,m_pSocket,0);

CFRunLoopAddSource(cRunRef,

sourceRef,

kCFRunLoopCommonModes

);

CFRelease(sourceRef);

CFRelease(address);

NSLog(@"连接成功1");

}

break;

caseAF_INET6://IPV6

{

structsockaddr_in6 *v6sa = (structsockaddr_in6 *)res->ai_addr;

v6sa->sin6_port =htons(port);

CFDataRef address6 =CFDataCreate(kCFAllocatorDefault, (UInt8 *)&v6sa,sizeof(v6sa));

//建立连接IPV6

CFSocketConnectToAddress(m_pSocket,

address6,

-1

);

CFRunLoopRef cRunRef =CFRunLoopGetCurrent();

CFRunLoopSourceRef sourceRef =CFSocketCreateRunLoopSource(kCFAllocatorDefault,m_pSocket,0);

CFRunLoopAddSource(cRunRef,

sourceRef,

kCFRunLoopCommonModes

);

CFRelease(sourceRef);

CFRelease(address6);

NSLog(@"连接成功2");

}

break;

}

//        函数说明:connect()用来将参数sockfd的socket连至参数serv_addr指定的网络地址.结构sockaddr请参考bind().参数addrlen为sockaddr的结构长度.

//

//        返回值:成功则返回0,失败返回-1,错误原因存于errno中.

//

//        错误代码:

//        1、EBADF参数sockfd非合法socket处理代码

//        2、EFAULT参数serv_addr指针指向无法存取的内存空间

//        3、ENOTSOCK参数sockfd为一文件描述词,非socket.

//        4、EISCONN参数sockfd的socket已是连线状态

//        5、   ETIMEDOUT企图连线的操作超过限定时间仍未有响应.

//        6、ENETUNREACH无法传送数据包至指定的主机.

//        7、EAFNOSUPPORT sockaddr结构的sa_family不正确.

//        8、EALREADY socket为不可阻断且先前的连线操作还未完成.

if (connect(s, res->ai_addr, res->ai_addrlen) < 0)//连接失败的处理

{

close(s);//关闭套接字描述

//socket 设置成非阻塞状态-------------很重要

flags = fcntl(s,F_GETFL,0);

fcntl(s,F_SETFL, flags |O_NONBLOCK);

//socket 设置成非阻塞状态-------------很重要

s = -1;

continue;

}

break;///连接成功就跳出循环

}

freeaddrinfo(res);

}

关闭socket---无用

//- (void)closeSocket

//{

//    CFSocketInvalidate(m_pSocket);

//}

//建立连接后的回调函数判断是否连接成功 (有数据返回说明没有连接成功)

static void TCPClientConnectCallBack(CFSocketRef socket,CFSocketCallBackType type,CFDataRef address,const void *data,void *info)

{

LTSocket *client = (LTSocket *)info;

if (data !=NULL)//有数据返回说明没有连接成功

{

NSLog(@"连接失败");

[client loginJudgeFalse:@"连接失败"];

return;

}

else

{

NSLog(@"连接成功");

//        LTSocket *client = (LTSocket *)info;

[client connectSuccess];//连接成功

[client StartReadThread];//开启线程,读取数据(如果在电机控制页面点击了开关,就会有数据产生)

[client sendLoginMessage];//发送登录的信息

[client sendHeartbeat];//发送心跳检测

}

}

//连接失败

- (void)connectFail

{

if (self.m_pDelegeate && [self.m_pDelegeaterespondsToSelector:@selector(socketConnectFail)])

{

[self.m_pDelegeatesocketConnectFail];

}

}

//连接成功

- (void)connectSuccess

{

if (self.m_pDelegeate && [self.m_pDelegeaterespondsToSelector:@selector(socketConnectSuccess)])

{

[self.m_pDelegeatesocketConnectSuccess];

}

}

//开启新线程,读取数据在这里面实现的

- (void)StartReadThread

{

m_pInitThread = [[NSThreadalloc]initWithTarget:selfselector:@selector(InitThreadFunc:)object:self];

[m_pInitThreadstart];

}

//

- (void)reconnectNetWork1

{

[selfstopTimer];//关闭定时器

if ([LTUserInfodefaultUserInfo].m_isInterrupt ==NO) {

if (self.m_pDelegeate && [self.m_pDelegeaterespondsToSelector:@selector(reconnectNetWork)])

{

[self.m_pDelegeatereconnectNetWork];

}

}

[LTUserInfodefaultUserInfo].m_isInterrupt =NO;

}

//读取数据在这里面实现

-(void)InitThreadFunc:(id)sender

{NSLog(@"标记1");

while (1) {

BOOL requestStop = [selfreadStream];//读取从服务器接收的数据(如果有数据返回YES,没有数据返回NO)

if (!requestStop)//走到这一步说明没有数据返回

{

NSLog(@"没有数据");

[m_pInitThreadcancel];//取消线程

[selfperformSelectorOnMainThread:@selector(reconnectNetWork1)withObject:nilwaitUntilDone:NO];//回到主线程执行reconnectNetWork方法

return;

}

}

}

//停止定时器

- (void)stopTimer{

if (self.heartbeatTimer) {

[self.heartbeatTimerinvalidate];//定时器失效

self.heartbeatTimer =nil;

}

}

//读取数据(读取服务器返回的数据)

- (BOOL)readStream

{

NSLog(@"标记2");

char buffer[1024];

NSAutoreleasePool *pool = [[NSAutoreleasePoolalloc]init];

memset(&buffer,0,sizeof(buffer));//用0覆盖前n个字节

//接收数据

ssize_t bufferSize =recv(CFSocketGetNative(m_pSocket), buffer,sizeof(buffer),0);//recv方法返回的数据<0出错 ,=0关闭连接 ,>接收到的数据大小(多少个字节)

NSLog(@"返回的数据----------------%s",buffer);

NSLog(@"bufferSize----------%zd",bufferSize);//返回的数据大小(所占的字节)

if (bufferSize <=0) {

returnNO;

}

//分析接收到的数据

//buffer是接收到的数据内容字符串;bufferSize是接收到的数据内容大小;

[selfresolveReceiveInfo:bufferBufNum:bufferSize];

memset(&buffer,0,sizeof(buffer));

[pool release];

pool= nil;

returnYES;

}

//连接失败

- (void)loginJudgeFalse:(NSString *)pMessage

{

if (m_pSocket) {

[LTUserInfodefaultUserInfo].m_isInterrupt =YES;

CFSocketInvalidate(m_pSocket);

}

if (self.m_pDelegeate && [self.m_pDelegeaterespondsToSelector:@selector(loginJudgeFalse:)])

{

[self.m_pDelegeateloginJudgeFalse:pMessage];

}

}

//发送登录信息

- (void)sendLoginMessage {

int num =26;

char *dataList = (char *)malloc(sizeof(char) * num);

memset(dataList,0,sizeof(char)*(num));

getHeadData(dataList);

getDeviceData(dataList);

for (NSInteger i =10; i <18; i++) {

dataList[i] = 0x00;

}

dataList[18] =0x00;

dataList[19] =0x01;

dataList[20] =0x00;///

dataList[21] =0x00;

dataList[22] =0x00;

getChecksum(dataList,23);

getEndData(dataList, num);

//    for (NSInteger i = 0; i < num; i++) {

//

//                NSLog(@"sendLoginMessage %d", dataList[i]);

//    }

send(CFSocketGetNative(m_pSocket), dataList, num,0);

free(dataList);

}

//定时器隔3秒发送心跳检测

- (void)sendHeartbeat

{

NSTimer *heartbeatTimer = [NSTimerscheduledTimerWithTimeInterval:3.0ftarget:selfselector:@selector(sendHeartbeatMessage)userInfo:nilrepeats:YES];

self.heartbeatTimer = heartbeatTimer;

}

//发送心跳检测信息

- (void)sendHeartbeatMessage

{

int num =27;

char *dataList = (char *)malloc(sizeof(char) * num);//分配内存空间

memset(dataList,0,sizeof(char)*(num));//将dataList中前n个字节(用 0替换并返回 dataList。

getHeadData(dataList);

getDeviceData(dataList);

dataList[10] =0x12;

dataList[11] =0x78;

dataList[12] =0xa0;

dataList[13] =0x9c;

dataList[14] =0x00;

dataList[15] =0x00;

dataList[16] =0x00;

dataList[17] =0x00;

dataList[18] =0x00;//

dataList[19] =0x02;//

dataList[20] =0x00;//

dataList[21] =0x00;

dataList[22] =0x01;

dataList[23] =0x00;

getChecksum(dataList,24);

getEndData(dataList, num);

send(CFSocketGetNative(m_pSocket), dataList, num,0);

free(dataList);

//     NSLog(@"发心跳包");

}

//发送控制单个电机开关的启消息

- (void)sendCtrSingleDeviceWithDeviceID:(NSString *)deviceID IsOpen:(BOOL)isOpen PondDeviceId:(char)pondDeviceId

{

int num =28;

char *dataList = (char *)malloc(sizeof(char) * num);

memset(dataList,0,sizeof(char)*(num));

getHeadData(dataList);//[0]-[5],帧头(1字节)-厂家信息(2字节)-终端版本号(1字节)-设备类型(2字节)

getCtrDeviceIDStr(dataList, deviceID);//[6]-[9],设备地址(4字节)--数据:00000000-FFFFFFFF

getCtrDeviceCommandSerial(dataList);//[10]-[17]命令流水号(8字节):由命令发起设备产生,应答设备接收后,原封不动进行回传,对命令进行对应。

/**

*具体操作命令字[18]-[19],不同的设备定义了不同的命令字;

*数据:0000-ffff

这里的10表示:数据上报间隔,用两个16进制表示;

*/

dataList[18] =0x00;

dataList[19] =0x10;

/**

操作标志:(1字节)[20]

(1)00主动上报,接收端此字节用0x80应答。

(2)01查询参数,接收端此字节用0x81应答。

(3)02设置参数,接收端此字节用0x82应答。

(4)03命令执行,接收端此字节用0x83应答。

(5)04命令关闭,接收端此字节用0x84应答。

*数据:00-01

*/

dataList[20] =0x02;

if (isOpen) {//开关打开时发送的数据0X01;

getCtrSingleDeviceData(dataList,0x01, pondDeviceId);//获取单个控制设备数据

}

else {//开关关闭时发送的数据0X00;

getCtrSingleDeviceData(dataList,0x00, pondDeviceId);//获取单个控制设备数据

}

getChecksum(dataList,25);//[25][26]和校验码(2字节),从帧头到具体数据的校验

getEndData(dataList, num);//[27]帧尾(1字节),数据#(对应的ASCII吗值是16进制ox23)

for (NSInteger i =0; i < num; i++) {

//        NSLog(@"控制设备 %d", dataList[i]);

}

/* 第一个参数指定发送端套接字描述符;

第二个参数指明一个存放应用程式要发送数据的缓冲区;

第三个参数指明实际要发送的数据的字符数;

第四个参数一般置0。*/

send(CFSocketGetNative(m_pSocket), dataList, num,0);//数据由指定 socket传给主机(服务器)

free(dataList);//释放malloc(或calloc、realloc)函数给指针变量分配的内存空间的函数

}

//发送一台机器所有电机(增氧,投饵,滴灌,风机,排污)开关的消息

- (void)sendCtrAllDeviceWithDeviceID:(NSString *)deviceID IsOpen:(BOOL)isOpen LTPondInfoModal:(LTPondInfoModal *)ltPondInfoModal

{

//如果发送的是全开命令,已经开启的电机就不发送命令了,如果发送的是全关命令,已经关闭的电机就不发送命令了;

NSArray *electricBackStateArr=ltPondInfoModal.electricBackStateArr;

NSLog(@"--pond--%@",electricBackStateArr);

NSString *electric=ltPondInfoModal.electrics;

NSArray *electricsArr=[electriccomponentsSeparatedByString:@","];

for(int i=0;i<electricsArr.count;i++){

if((![electricBackStateArr[i]isEqualToString:@"1"]&&isOpen==YES)||(![electricBackStateArr[i]isEqualToString:@"0"]&&isOpen==NO)){

NSString *str=[NSStringstringWithFormat:@"0x0%d",i+1];

unsignedint deviceIDs;

[[NSScannerscannerWithString:str]scanHexInt:&deviceIDs];

char c=(char) deviceIDs;

//        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

//

//        });

[selfsendCtrSingleDeviceWithDeviceID:deviceIDIsOpen:isOpenPondDeviceId:c];//发送单个电机控制

if(electricsArr.count==7&&i==6){

//必须用GCD延迟执行,并配合socket中的线程改成非阻塞

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5*NSEC_PER_SEC)),dispatch_get_main_queue(), ^{

[selfsendCtrSingleDeviceWithDeviceID:deviceIDIsOpen:isOpenPondDeviceId:0x07];

NSLog(@"第七路执行了");

});

}

if(electricsArr.count==8&&i==7){

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 *NSEC_PER_SEC)),dispatch_get_main_queue(), ^{

[selfsendCtrSingleDeviceWithDeviceID:deviceIDIsOpen:isOpenPondDeviceId:0x07];

[selfsendCtrSingleDeviceWithDeviceID:deviceIDIsOpen:isOpenPondDeviceId:0x08];

NSLog(@"第八路执行了");

});

}

//

}

}

return;

}

//数据包长度[21]-[22]和具体的数据[23]-[24]

void getCtrSingleDeviceData(char *dataList,char openData,char pondDeviceId)

{

/**(2字节)由不同设备之间的通信和业务,决定具体数据包长度。

*数据包长度,N字节(数据包占N个字节的长度)

*数据:N

*把N用两个字节的16进制表示;

*/

dataList[21] =0x00;

dataList[22] =0x02;

/**

*具体的数据(2字节)

*

*/

dataList[23] = pondDeviceId;//把单个的电机号赋值给他

dataList[24] = openData;   //0x01表示开,0x00表示关;

}

//获取所有控制设备数据

void getCtrAllDeviceData(char *dataList,char openData)

{

dataList[21] =0x00;

dataList[22] =0x04;

dataList[23] =0x01;

dataList[24] = openData;

dataList[25] =0x02;

dataList[26] = openData;

/// ///lb

//    dataList[27] = 0x03;

//    dataList[28] = openData;

//

//    dataList[29] = 0x04;

//    dataList[30] = openData;

//

//    dataList[31] = 0x05;

//    dataList[32] = openData;

//    dataList[33] = 0x06;

//    dataList[34] = openData;

//

//    dataList[35] = 0x07;

//    dataList[36] = openData;

//

//    dataList[37] = 0x08;

//    dataList[38] = openData;

// ///lb

}

//设备地址,由DeviceID分解得到

void getCtrDeviceIDStr(char *dataList,NSString *deviceIDStr)

{

NSArray *deviceIDs = [deviceIDStrcomponentsSeparatedByString:@"-"];

for (NSInteger i =0; i < [deviceIDscount]; i++) {

NSString *deviceIDStr = [deviceIDsobjectAtIndex:i];

unsignedint deviceID;

[[NSScannerscannerWithString:deviceIDStr]scanHexInt:&deviceID];

if (i ==0) {

dataList[6] = (char)deviceID;

}

elseif (i ==1) {

dataList[7] = (char)deviceID;

}

elseif (i ==2) {

dataList[8] = (char)deviceID;

}

elseif (i ==3) {

dataList[9] = (char)deviceID;

}

}

}

//命令流水号(8字节):由命令发起设备产生,应答设备接收后,原封不动进行回传,对命令进行对应。

void getCtrDeviceCommandSerial(char *dataList)

{

dataList[10] =0x12;

dataList[11] =0x78;

dataList[12] =0xa0;

dataList[13] =0x9c;

dataList[14] =0x00;

dataList[15] =0x00;

dataList[16] =0x00;

dataList[17] =0x00;

}

void getHeadData(char *dataList)

{    //帧头(1字节)数据:*(对应的是16进制0x2a)

dataList[0] =0x2a;

//厂家信息:(2字节)数据:HS , H(ASCII码16进制是0x48),S(ASCII码16进制是0x53)

dataList[1] =0x48;

dataList[2] =0x53;

//版本号,终端版本号(1字节),数据:1-255

dataList[3] =0x03;

//设备类型(2字节),见表设备类型分类,数据:0001-FFFF

dataList[4] =0x00;

dataList[5] =0xfe;///这个和水产协议规范的不一样,水产协议是从0,1,2,3,4.......

}

//设备地址(4个字节),数据:00000000-FFFFFFFF

void getDeviceData(char *dataList){

LTUserInfo *userInfo = [LTUserInfodefaultUserInfo];

dataList[6] = userInfo.deviceFriID;//这里的deviceFriID是从loginresult的到,也就是customNO;

dataList[7] = userInfo.deviceSecID;

dataList[8] = userInfo.deviceThiID;//

dataList[9] = userInfo.deviceFouID;//机器号/池塘号

}

//[25][26]和校验码(2字节),从帧头到具体数据的校验,对数据内容的正确性进行验证。数据校验共2个字节,和校验,超过0XFFFF,溢出;

void getChecksum(char *dataList,int checkDataNum)

{

NSInteger sum =0;

for (NSInteger i =0; i < checkDataNum; i++) {

sum += dataList[i] & 0xff;

}

//    NSLog(@"sum--------------%zd",sum);

dataList[checkDataNum] = (sum & 0xff00) >>8;//十进制的1062和0xff位与运算再又移8位,得到结果0x4;

dataList[checkDataNum + 1] = sum &0x00ff;//10进制的1062和0xff位与运算,得到0x26

}

//帧尾,数据:#(ASCII码16进制是0x23)

void getEndData(char *dataList,int dataNum)

{

dataList[dataNum - 1] =0x23;

}

#pragma mark -----处理各台电机控制的传感器实时返回的数据

//在readStream方法中调用的下面这个方法

- (void)resolveReceiveInfo:(char *)dataBuf BufNum:(NSInteger)bufNum

{

[selfgetReceiveAllData:dataBufBufNum:bufNum];

}

//获取所有接收到的数据

- (void)getReceiveAllData:(char *)dataBuf BufNum:(NSInteger)bufNum

{NSLog(@"标记3");

NSInteger startNum =0;

BOOL isHaveData =NO;//是否有数据的标示,此处标示没有数据

for (NSInteger i =0; i <100; i++) {

NSInteger endNum = [selfgetReceiveEndDataNum:dataBufBufNum:bufNumStartNum:startNum];//这个方法里面有获取实时返回的数据,并设置每一个池塘的模型中各项指标的数据

if (endNum == -1) {

NSLog(@"socket receive error");

break;

}

isHaveData = YES;

if (endNum +1 == bufNum) {

break;

}

}

if (isHaveData ==YES) {

[selfgetReceivePondDataForMainWithpondInfoModel:self.ltPondInfoModal];//回到主线程执行getReceivePondData(通过代理LTRealTimeViewController执行,刷新池塘模型的数据)

}

}

//回到主线程执行getReceivePondData(通过代理LTRealTimeViewController执行,刷新池塘模型的数据)

- (void)getReceivePondDataForMainWithpondInfoModel:(LTPondInfoModal *)ltPondInfoModal

{NSLog(@"标记6");

[selfperformSelectorOnMainThread:@selector(getReceivePondData:)withObject:nilwaitUntilDone:NO];

}

- (void)getReceivePondData:(LTPondInfoModal *)ltPondInfoModal

{

if (self.m_pDelegeate && [self.m_pDelegeaterespondsToSelector:@selector(getReceivePondData:)])

{

[self.m_pDelegeategetReceivePondData:ltPondInfoModal];

}

}

将NSString转换成十六进制的字符串则可使用如下方式:

- (NSString *)ToHex:(uint16_t)tmpid

{

NSString *nLetterValue;

NSString *str =@"";

uint16_t ttmpig;

NSString *n1;

//    for (int i = 0; i<9; i++) {

ttmpig=tmpid%16;

tmpid=tmpid/16;

switch (ttmpig)

{

case10:

nLetterValue =@"A";break;

case11:

nLetterValue =@"B";break;

case12:

nLetterValue =@"C";break;

case13:

nLetterValue =@"D";break;

case14:

nLetterValue =@"E";break;

case15:

nLetterValue =@"F";break;

default:

nLetterValue = [NSStringstringWithFormat:@"%u",ttmpig];

}

//        str = [nLetterValue stringByAppendingString:str];

if (tmpid ==0) {

str=[str stringByAppendingString:[NSStringstringWithFormat:@"0%@",nLetterValue]];

return str;

}

if(tmpid >0 && tmpid<=16){

switch (tmpid)

{

case10:

n1 =@"A";break;

case11:

n1 =@"B";break;

case12:

n1 =@"C";break;

case13:

n1 =@"D";break;

case14:

n1 =@"E";break;

case15:

n1 =@"F";break;

default:

n1 = [NSStringstringWithFormat:@"%u",tmpid];

}

str = [n1 stringByAppendingString:nLetterValue];

}

//    }

return str;

}

//这个方法里面有获取实时返回的数据,并设置每一个池塘的模型中各项指标的数据

- (NSInteger)getReceiveEndDataNum:(char *)dataBuf BufNum:(NSInteger)bufNum StartNum:(NSInteger)startNum

{NSLog(@"标记4");

/**

*startNum-----0

*bufNum------返回的数据长度

*dataBuf------返回的数据字符串

*

*/

if (startNum +22 >=  bufNum) {

return -1;

}

NSInteger  dataNum = ((dataBuf[startNum +21] &0xff) <<8) + (dataBuf[startNum +22] &0xff);

NSLog(@"dataNum-----------%zd",dataNum);

NSString *str=@"";

if((int)bufNum>=71){

for(int i=0;i<(int)bufNum;i++){

//        NSLog(@"dataBuff-01-**%@----%zd",[NSString stringWithFormat:@"%d",i],  dataBuf[i] & 0xff);

//        NSString *cs01=[NSString stringWithFormat:@"%c",dataBuf[i] & 0xff];

NSString *tenToHex=[selfToHex:dataBuf[i]&0xff];//10进制的转换成16进制

NSLog(@"dataBuff-01-**%@----%@",[NSStringstringWithFormat:@"%d",i],tenToHex);

//拼接字符串

str=[str stringByAppendingString:tenToHex];

//电机的返回状态*

NSString *electricBackstatuteFirst=[[selfToHex:dataBuf[64]&0xff]substringToIndex:1];

NSString *electricBackstatuteSecond=[[selfToHex:dataBuf[64]&0xff]substringFromIndex:1];

NSString *electricBackstatuteThird=[[selfToHex:dataBuf[65]&0xff]substringToIndex:1];

NSString *electricBackstatuteForth=[[selfToHex:dataBuf[65]&0xff]substringFromIndex:1];

NSString *electricBackstatuteFifth=[[selfToHex:dataBuf[66]&0xff]substringToIndex:1];

NSString *electricBackstatuteSixth=[[selfToHex:dataBuf[66]&0xff]substringFromIndex:1];

NSString *electricBackstatuteSeventh=[[selfToHex:dataBuf[67]&0xff]substringToIndex:1];

NSString *electricBackstatuteEighth=[[selfToHex:dataBuf[67]&0xff]substringFromIndex:1];

NSMutableArray *electricBackStaArr=[[NSMutableArrayalloc]init];

[electricBackStaArr addObject:electricBackstatuteFirst];

[electricBackStaArr addObject:electricBackstatuteSecond];

[electricBackStaArr addObject:electricBackstatuteThird];

[electricBackStaArr addObject:electricBackstatuteForth];

[electricBackStaArr addObject:electricBackstatuteFifth];

[electricBackStaArr addObject:electricBackstatuteSixth];

[electricBackStaArr addObject:electricBackstatuteSeventh];

[electricBackStaArr addObject:electricBackstatuteEighth];

self.electricBackstateArr=electricBackStaArr;

//电机的返回状态*

}

}

NSLog(@"返回的数据-%tu条--%@",bufNum,str);

if (startNum +25 + dataNum >= bufNum) {

return -1;

}

if (dataBuf[startNum +25 + dataNum] !=0x23) {

return -1;

}

char checkBuf1 = dataBuf[startNum +18] &0xff;

char checkBuf2 = dataBuf[startNum +19] &0xff;

if (checkBuf1 ==0x00 && checkBuf2 ==0x03) {

//[18]-[19]如果是0x00,0x03表示是检测数据上报

NSLog(@"标记***!");

[selfgetRealTimeData:dataBufStartNum:startNum];//获取实时数据,并设置每个池塘的模型中的指标数据

}

else {

NSLog(@"标记****2!");

[selfcheckDeviceOnline:dataBufStartNum:startNum];//设置在线/离线状态

}

return startNum +25 + dataNum;

}

//获取实时数据,并设置每个池塘的模型中的指标数据

- (void)getRealTimeData:(char *)dataBuf StartNum:(NSInteger)startNum

{   NSLog(@"标记5");

LTPondInfoModal *pondInfoModal = [selfgetPondInfoWithDeviceFriID:dataBuf[startNum +6] DeviceSecID:dataBuf[startNum +7]DeviceThiID:dataBuf[startNum +8]DeviceFouID:dataBuf[startNum +9]];//通过返回数据的第6.7.8.9的位置字符来判断并获取池塘模型

self.ltPondInfoModal=pondInfoModal;

NSInteger dataNum = (dataBuf[startNum +21] <<8) + dataBuf[startNum +22];

NSInteger startDataNum =23 + startNum;

NSInteger num = dataNum /5;

for (NSInteger i =0; i < num; i++) {

NSInteger dataRealTimeType = dataBuf[startDataNum];

unsignedchar dataBuf1 = dataBuf[startDataNum +1];

unsignedchar dataBuf2 = dataBuf[startDataNum +2];

unsignedchar dataBuf3 = dataBuf[startDataNum +2];

unsignedchar dataBuf4 = dataBuf[startDataNum +3];

int dataNum = ((dataBuf1 &0xff) <<24) + ((dataBuf2 &0xff) <<16) + ((dataBuf3 &0xff) <<8) + (dataBuf4 &0xff);

float floatNum = *((float *)&dataNum);

if (dataRealTimeType ==1) {

pondInfoModal.doData = floatNum;

NSLog(@"-服务器-溶解氧1*******--%f",pondInfoModal.doData);

//溶氧警告设置

[selfgetDeviceWarningAerobics:pondInfoModalFloatNum:floatNum];

}

elseif (dataRealTimeType ==2) {

pondInfoModal.dissolvedData = floatNum;

NSLog(@"--溶解氧饱和度1*******--%f",pondInfoModal.dissolvedData);

}

elseif (dataRealTimeType ==3) {

pondInfoModal.phData = floatNum;

NSLog(@"-服务器-PH1*******--%f",pondInfoModal.phData);

}

elseif (dataRealTimeType ==4) {

pondInfoModal.ammoniaData = floatNum;

}

elseif (dataRealTimeType ==5) {

pondInfoModal.temperatureData = floatNum;

NSLog(@"-服务器-温度1******---%f",pondInfoModal.temperatureData);

}

elseif (dataRealTimeType ==6) {

pondInfoModal.nitriteData = floatNum;

}

elseif (dataRealTimeType ==7) {

pondInfoModal.levelData = floatNum;

}

elseif (dataRealTimeType ==8) {

pondInfoModal.hydrogenSulfideData = floatNum;

}

elseif (dataRealTimeType ==9) {

pondInfoModal.turbidityData = floatNum;

}

elseif (dataRealTimeType ==10) {

pondInfoModal.salinityData = floatNum;

}

elseif (dataRealTimeType ==11) {

pondInfoModal.conductivityData = floatNum;

}

elseif (dataRealTimeType ==12) {

pondInfoModal.codData = floatNum;

}

elseif (dataRealTimeType ==13) {

pondInfoModal.atmosphericPressureData = floatNum;

}

elseif (dataRealTimeType ==14) {

pondInfoModal.windVelocityData = floatNum;

}

elseif (dataRealTimeType ==15) {

pondInfoModal.windDirectionData = floatNum;

}

elseif (dataRealTimeType ==16) {

pondInfoModal.chlorophyllData = floatNum;

}

elseif (dataRealTimeType ==17) {

pondInfoModal.airTemperatureData = floatNum;

}

elseif (dataRealTimeType ==18) {

pondInfoModal.atmosphericHumidityData = floatNum;

}

NSDateFormatter* formatter = [[NSDateFormatteralloc]init];

formatter.dateFormat =@"yyyy-MM-dd HH:mm:ss";

NSString *dateStr = [formatterstringFromDate:[NSDatedate]];

pondInfoModal.lastDateStr = dateStr;

startDataNum += 5;

if(pondInfoModal){//

pondInfoModal.isOnline =@"在线";

pondInfoModal.electricBackStateArr=self.electricBackstateArr;

//延迟执行

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 *NSEC_PER_SEC)),dispatch_get_main_queue(), ^{

//发送通知显示电机状态

[[NSNotificationCenterdefaultCenter]postNotificationName:@"feedBackState"object:niluserInfo:@{@"pondInfoModal":pondInfoModal}];

});

}else{

pondInfoModal.isOnline=@"离线";

}

}

}

//溶氧警告设置

- (void)getDeviceWarningAerobics:(LTPondInfoModal *)pondInfoModal FloatNum:(CGFloat)floatNum

{

//设置的塘口集合

LTSetAerobicsStatictics *setAerobics = [LTSetAerobicsStaticticsdefaultSetAerobicsStatictics];

NSMutableArray *setAerobicsList = setAerobics.setAerobicsList;

if(setAerobicsList.count!=0){

for(int i=0;i<[setAerobicsListcount];i++){

LTPondAerobicsInfo *pondAerobicsInfo = [setAerobicsListobjectAtIndex:i];//设置的一个塘口的数据

CGFloat upperAerobics = [pondAerobicsInfo.upperAerobicsfloatValue];

CGFloat lowerAerobics = [pondAerobicsInfo.lowerAerobicsfloatValue];

//如果pondAerobicsInfo.upperAerobics和lowerAerobics不为空,说明设置了溶氧警告,就把实时返回的溶氧值添加到警告的数组

if(![pondAerobicsInfo.upperAerobicsisEqualToString:@""]&&![pondAerobicsInfo.lowerAerobicsisEqualToString:@""]){

if ([pondAerobicsInfo.deviceIDisEqualToString:pondInfoModal.deviceID]) {

if (upperAerobics >0.0 && lowerAerobics >0.0) {

if (floatNum > upperAerobics || floatNum < lowerAerobics) {

//设置返回的溶氧数据

[[LTAerobicsWarningStaticticsdefaultAerobicsWarningStatictics]addAerobicsWarningStatictics:floatNumDeviceID:pondInfoModal.deviceID LTSetAerobicsStaticticsArr:setAerobicsListnum:pondAerobicsInfo.pTag];

[selfplaceVoice];//溶氧警告

}

}//            return;

}

}elseif([pondAerobicsInfo.upperAerobicsisEqualToString:@""]&&[pondAerobicsInfo.lowerAerobicsisEqualToString:@""]){

//如果pondAerobicsInfo.upperAerobics和lowerAerobics为空,说明没有设置溶氧警告。

}

}

}

}

//设置在线离线状态

- (void)checkDeviceOnline:(char *)dataBuf StartNum:(NSInteger)startNum

{

LTPondInfoModal *pondInfoModal = [selfgetPondInfoWithDeviceFriID:dataBuf[startNum +6] DeviceSecID:dataBuf[startNum +7]DeviceThiID:dataBuf[startNum +8]DeviceFouID:dataBuf[startNum +9]];

if (pondInfoModal ==nil) {

return;

}

if ((dataBuf[startNum +18] ==0) && (dataBuf[startNum +19] == -2)) {

//        NSLog(@"%@ 设备在线", pondInfoModal.deviceID);

pondInfoModal.isOnline =@"在线";

}

else if ((dataBuf[startNum + 18] == 0) && (dataBuf[startNum +19] == -3)) {

//        NSLog(@"%@ 设备离线", pondInfoModal.deviceID);

pondInfoModal.isOnline =@"离线";///

}

}

//判断并获取池塘模型

- (LTPondInfoModal *)getPondInfoWithDeviceFriID:(char)deviceFriID DeviceSecID:(char)deviceSecID DeviceThiID:(char)deviceThiID DeviceFouID:(char)deviceFouID

{

NSMutableArray *deviceInfoList = [LTUserInfodefaultUserInfo].deviceInfoList;

for (NSInteger i =0; i < [deviceInfoListcount]; i++) {

LTDeviceInfoModal *deviceInfo = [deviceInfoListobjectAtIndex:i];

for (NSInteger j =0; j < [deviceInfo.pondListcount]; j++) {

LTPondInfoModal *pondInfoModal = [deviceInfo.pondListobjectAtIndex:j];

if ((deviceFriID == pondInfoModal.deviceFriID) && (deviceSecID == pondInfoModal.deviceSecID) && (deviceThiID == pondInfoModal.deviceThiID) && (deviceFouID == pondInfoModal.deviceFouID)) {

return pondInfoModal;

}

}

}

returnnil;

}

#pragma mark - 科大讯飞的语音系统

#pragma mark - 播放警报

- (void)placeVoice

{

NSLog(@"溶氧警告");

}

- (void)onStart

{

}

- (CGFloat)hexChangeFloat:(int)dataNum

{

CGFloat floatNum = *((CGFloat *)&dataNum);

return floatNum;

}

- (int)floatChangeFloat:(float)dataNum

{

int intNum = *((int *)&dataNum);

return intNum;

}

- (void)getRealTimeData1:(char *)dataBuf BufNum:(NSInteger)bufNum

{

if (bufNum <40) {

return;

}

//    NSLog(@"getRealTimeData");

LTPondInfoModal *pondInfoModal =nil;

NSMutableArray *deviceInfoList = [LTUserInfodefaultUserInfo].deviceInfoList;

for (NSInteger i =0; i < [deviceInfoListcount]; i++) {

LTDeviceInfoModal *deviceInfo = [deviceInfoListobjectAtIndex:i];

for (NSInteger j =0; j < [deviceInfo.pondListcount]; j++) {

LTPondInfoModal *tmpPondInfoModal = [deviceInfo.pondListobjectAtIndex:j];

if ((dataBuf[6] == tmpPondInfoModal.deviceFriID) && (dataBuf[7] == tmpPondInfoModal.deviceSecID) && (dataBuf[8] == tmpPondInfoModal.deviceThiID) && (dataBuf[9] == tmpPondInfoModal.deviceFouID)) {

pondInfoModal = tmpPondInfoModal;

//                NSLog(@"我要  deviceid %@", pondInfoModal.deviceID);

break;

}

}

}

NSInteger dataNum = (dataBuf[21] <<8) + dataBuf[22];

NSInteger startNum =23;

NSInteger num = dataNum /5;

for (NSInteger i =0; i < num; i++) {

NSInteger dataRealTimeType = dataBuf[startNum];

unsignedchar dataBuf1 = dataBuf[startNum +1];

unsignedchar dataBuf2 = dataBuf[startNum +2];

unsignedchar dataBuf3 = dataBuf[startNum +2];

unsignedchar dataBuf4 = dataBuf[startNum +3];

NSInteger dataNum = ((dataBuf1 &0xff) <<24) + ((dataBuf2 &0xff) <<16) + ((dataBuf3 &0xff) <<8) + (dataBuf4 &0xff);

CGFloat floatNum = *((CGFloat *)&dataNum);

if (dataRealTimeType ==1) {

pondInfoModal.doData = floatNum;

}

elseif (dataRealTimeType ==2) {

pondInfoModal.dissolvedData = floatNum;

}

elseif (dataRealTimeType ==3) {

pondInfoModal.phData = floatNum;

}

elseif (dataRealTimeType ==4) {

pondInfoModal.ammoniaData = floatNum;

}

elseif (dataRealTimeType ==5) {

pondInfoModal.temperatureData = floatNum;

}

elseif (dataRealTimeType ==6) {

pondInfoModal.nitriteData = floatNum;

}

elseif (dataRealTimeType ==7) {

pondInfoModal.levelData = floatNum;

}

elseif (dataRealTimeType ==8) {

pondInfoModal.hydrogenSulfideData = floatNum;

}

elseif (dataRealTimeType ==9) {

pondInfoModal.turbidityData = floatNum;

}

elseif (dataRealTimeType ==10) {

pondInfoModal.salinityData = floatNum;

}

elseif (dataRealTimeType ==11) {

pondInfoModal.conductivityData = floatNum;

}

elseif (dataRealTimeType ==12) {

pondInfoModal.codData = floatNum;

}

elseif (dataRealTimeType ==13) {

pondInfoModal.atmosphericPressureData = floatNum;

}

elseif (dataRealTimeType ==14) {

pondInfoModal.windVelocityData = floatNum;

}

elseif (dataRealTimeType ==15) {

pondInfoModal.windDirectionData = floatNum;

}

elseif (dataRealTimeType ==16) {

pondInfoModal.chlorophyllData = floatNum;

}

elseif (dataRealTimeType ==17) {

pondInfoModal.airTemperatureData = floatNum;

}

elseif (dataRealTimeType ==18) {

pondInfoModal.atmosphericHumidityData = floatNum;

}

startNum += 5;

}

[selfperformSelectorOnMainThread:@selector(getReceivePondDataForMainWithpondInfoModel:)withObject:nilwaitUntilDone:NO];

}

- (BOOL)isRealTimeData:(char *)dataBuf

{

char data1 = dataBuf[10];

char data2 = dataBuf[11];

char data3 = dataBuf[12];

char data4 = dataBuf[13];

char data5 = dataBuf[14];

char data6 = dataBuf[15];

char data7 = dataBuf[16];

char data8 = dataBuf[17];

if ((data1 ==18) && (data2 ==120) && (data3 == -96) && (data4 == -100) && (data5 ==0) && (data6 == 0) && (data7 ==0) && (data8 ==0)) {

returnYES;

}

returnNO;

}

@end

C语言Socket之iOS项目中的socket应用/IPV6 转换/域名转IP/解析socket接受的数据/心跳包相关推荐

  1. XamarinSQLite教程Xamarin.iOS项目中打开数据库文件

    XamarinSQLite教程Xamarin.iOS项目中打开数据库文件 以下是打开MyDocuments.db数据库的具体操作步骤: (1)将Mac电脑上的MyDocuments.db数据库移动到W ...

  2. XamarinSQLite教程在Xamarin.iOS项目中定位数据库文件

    XamarinSQLite教程在Xamarin.iOS项目中定位数据库文件 开发者可以在指定的路径中找到复制的数据库文件,具体的操作步骤如下: (1)单击Mac电脑中Finder菜单中的"前 ...

  3. 在Xamarin.iOS项目中使用预设数据库

    在Xamarin.iOS项目中使用预设数据库 当开发者准备好一个预设数据库文件后,就可以将这个数据库文件添加到创建的项目中了.本节将分别在Xamarin.iOS和Xamarin.Android项目中使 ...

  4. 给iOS项目中添加图片,并通过UIImageView引用和显示该UIImage图片

    [问题] 关于iOS/iPhone中的文件选择对话框,用于用户去选择图片等文件 过程中,问题转换为,需要给当前iOS项目中,添加一个图片. 类似于Windows开发中的资源文件,其中图片文件属于资源的 ...

  5. iOS项目中的网络请求和上下拉刷新封装

    代码地址如下: http://www.demodashi.com/demo/11621.html 一.运行效果图 现在的项目中不可避免的要使用到网络请求,而且几乎所有软件都有上下拉刷新功能,所以我在此 ...

  6. ios项目中调用百度地图iphone版与百度地图HDipad版的坑

    最近在写项目的时候发现了项目中调用百度地图的一个坑,iphone版与ipad版的不同. 一.首先百度地图在ipad上叫百度地图HD,要区分有GPS和没GPS版,也就是说没GPS的没有导航功能,在使用项 ...

  7. AR!!!高通Vuforia-iOS-SDK 和官方Demo 集成到iOS 项目中所需要注意的几点.

    AR!!!高通Vuforia-iOS-SDK 和官方Demo 集成到iOS 项目中所需要注意的几点. 首先,要说明一下,博主是一名AR小白,根据公司的计划,要我往Vuforia iOS原生 + 项目i ...

  8. iOS 项目中 网络请求Alamofire 的二次封装

    iOS 项目中 网络请求Alamofire 的二次封装 1.先创建 网络请求的工具类 NetWorkTool 继承自NSObject class NetWorkTool: NSObject {} 2. ...

  9. iOS项目中引入pod管理工具

    在Ios项目中引入pod工具管理三方库文件的步骤: 一.安装 安装CocoaPods 我的环境为Mac OS X 10.9.1,安装CocoaPods之前,先确保本地有Ruby环境,因为CocoaPo ...

最新文章

  1. Failed to instantiate one or more classes
  2. linux xxd查看二进制文件命令
  3. 英特尔史上最大收购!英特尔拟300亿美元收购GF,审批成关键!
  4. CreateEvent(NULL,TRUE,FALSE,NULL);的解释
  5. oracle 查看表结构约束,oracle 约束
  6. php 单元测试 静态类,可选的PHP类型提示/检查单元测试或静态分析?
  7. 「PowerBI」分析服务多维数据结构重回关系数据库的一大绝招
  8. 个人作业5——软工个人总结
  9. 【python】爬虫入门书籍推荐
  10. 2021中青杯数学建模A题
  11. c语言色电阻环编程,c 语言的计算(电阻)请问要如何用C计算电阻的三色环如~~宗 黑 红 ==1K#include #include #in...
  12. 机器人核心期刊及会议
  13. 利用Backtrader进行期权回测之五:用backtrader_plotting查看回测结果
  14. 干货|Android系统定制开发基础篇
  15. DOS操作系统的一些常用命令
  16. 【历史上的今天】9 月 17 日:世界上的第一张火车票;GamerDNA 创始人出生;中国开设第一个网上多媒体讲座
  17. Python curses使用
  18. 辅助 Excel 的数据计算 add-ins
  19. ESR传感器状态ESR-SENS
  20. DFF理解——转自知乎

热门文章

  1. nanosleep php,PHP time_nanosleep( )用法及代码示例
  2. 《大数据+AI在大健康领域中最佳实践前瞻》---- 连续血糖监测(CGM) 初探
  3. golang gin框架 CURD
  4. c++ dlopen、dlsym
  5. 自己推荐几本书。。。
  6. Microsoft Office PowerPoint 2007 文字重叠
  7. 重庆职称计算机考试网,重庆职称计算机考试大纲
  8. 关于IPv6自动配置地址 RA里的A、M、O标记位(纯理论无实验)
  9. 有什么P图抠图的工具?几个步骤轻松处理
  10. AutoJs学习-关于各种头条阅读自动赚金币的思路-实践上