数据传输 -- 字符串报文
1. 字符串报文分类: 固定长度字符串报文, 固定分隔符字符串报文。
2. 字符串报文组包
3. 字符串报文解析
字符串报文结构体:
typedef struct STRRESVARstu { int nAmount; //数据域总数 int nFlag; //报文类型 0定长域 1分割域 int *filedlen; //每个数据域的长度 int nCompartlen; //分割符号的长度 char szCompart[10]; //分隔符符串 char **filedaddr; //指向每个数据域首地址的指针 } STRRESVAR;
4. 示例一
#include <iostream> #include <string.h> #include <assert.h> #include <stdlib.h> using namespace std; #define STRSTR 0 #define STRINT 1 #define STRDOUBLE 2 typedef struct STRRESVARstu //字符串报文结构体 { int nAmount; int nFlag; int *filedlen; int nCompartlen; char szCompart[10]; char **filedaddr; } STRRESVAR; typedef STRRESVAR * PSTRRESVAR; int strrespre(char *buf, PSTRRESVAR pStrstu) //解析报文,报文先存储在buf中, pStrstu 为报文结构指针 { int i = 0, j = 0; char *p1, *p2; assert(buf != NULL && pStrstu != NULL && pStrstu->filedlen != NULL); assert(pStrstu->filedaddr != NULL); if (pStrstu->nFlag == 0) { for (i=0; i<pStrstu->nAmount; i++) { pStrstu->filedaddr[i] = buf + j; j = j + pStrstu->filedlen[i] + pStrstu->nCompartlen; } } else { p1 = buf; p2 = p1; while (p1 != NULL && i<= pStrstu->nAmount) { pStrstu->filedaddr[i] = p1; p2 = strstr(p1, pStrstu->szCompart); if (p2 == NULL) { pStrstu->filedlen[i] = strlen(p1); p1 = NULL; } else { pStrstu->filedlen[i] = p2 - p1; p1 = p2 + pStrstu->nCompartlen; } i++; } } return 0; } char * TrimString(char* szDest) //去字符串 首尾 空白 { int n, nLen; if (szDest != NULL) { for (n = strlen(szDest); n > 0; n--) { if (!isblank(szDest[n - 1])) break; } szDest[n] = '\0'; nLen = strlen(szDest); for (n = 0; n < nLen; n++) { if (!isblank(szDest[n])) break; } strcpy(szDest, szDest + n); } return szDest; } int strresvalue(char *buf, STRRESVAR Strstu, int nIndex, void *pValue, int nType) //报文数据域 读取 { char szStrbuf[1024]; assert(buf != NULL && pValue != NULL); assert(Strstu.filedlen != NULL && Strstu.filedaddr != NULL); assert(nIndex >=0 && nIndex < Strstu.nAmount); memset(szStrbuf, 0, sizeof(szStrbuf)); strncpy(szStrbuf, Strstu.filedaddr[nIndex],Strstu.filedlen[nIndex]); TrimString(szStrbuf); switch (nType) { case STRINT : *(int *)pValue = atoi(szStrbuf); break ; case STRDOUBLE: *(double *)pValue = atoi(szStrbuf); break; default: strcpy((char *)pValue, szStrbuf); break; } return 0; } /* int main() { cout << "Test Message!" << endl; char szCestr[] = "0019999999999999999999kevinX 1234567.89"; //定长报文 int nCelen[4] = {3, 19, 6, 12}; int nIndex; char *nCeAddr[4], szAccno[20], szName[20]; double fAmt; STRRESVAR stuStr; stuStr.nAmount = 4; stuStr.nFlag = 0; stuStr.filedlen = nCelen; stuStr.nCompartlen = 0; stuStr.szCompart[0] = 0; stuStr.filedaddr = nCeAddr; strrespre(szCestr, &stuStr); strresvalue(szCestr, stuStr, 0, &nIndex, STRINT); strresvalue(szCestr, stuStr, 1, szAccno, STRSTR); strresvalue(szCestr, stuStr, 2, szName, STRSTR); strresvalue(szCestr, stuStr, 3, &fAmt, STRDOUBLE); cout << "id = " << nIndex << endl; cout << "accno = " << szAccno << endl; cout << "name = " << szName << endl; cout << "amt = " << showpoint << fAmt << endl; return 0; } */ int main() { cout << "Test Message!" << endl; char szCestr[] = "2|!88888888|!kevin_xiang|!1234567.89"; //定分割域报文 int nIndex, nCeLen[4]; char *nCeAddr[4], szAccno[20], szName[20]; double fAmt; STRRESVAR stuStr; stuStr.nAmount = 4; stuStr.nFlag = 1; stuStr.filedlen = nCeLen; stuStr.nCompartlen = 2; strcpy(stuStr.szCompart, "|!"); stuStr.filedaddr = nCeAddr; strrespre(szCestr, &stuStr); strresvalue(szCestr, stuStr, 0, &nIndex, STRINT); strresvalue(szCestr, stuStr, 1, szAccno, STRSTR); strresvalue(szCestr, stuStr, 2, szName, STRSTR); strresvalue(szCestr, stuStr, 3, &fAmt, STRDOUBLE); cout << "id = " << nIndex << endl; cout << "accno = " << szAccno << endl; cout << "name = " << szName << endl; cout << "amt = " << showpoint << fAmt << endl; return 0; }
5. 示例二: linux下C读取 ini配置文档
需要上面例一 申明的结构体与函数
config.ini文件内容
[SERVER]
NUM=2
[SERVER1]
IP=192.168.0.1
PORT=8888
[SERVER2]
IP=192.168.0.2
PORT=5555
int GetConfigStrValue(char *buf, void *pValue, int nType) //配置项字符串读写 { char *nCeAddr[2]; int nCeLen[2]; STRRESVAR stuStr; stuStr.nAmount = 2; stuStr.nFlag = 1; stuStr.filedlen = nCeLen; stuStr.nCompartlen = 1; strcpy(stuStr.szCompart, "="); stuStr.filedaddr = nCeAddr; strrespre(buf, &stuStr); assert(strresvalue(buf, stuStr, 1, pValue, nType) == 0); return 0; } int GetConfigValue(char *szPath, char *szRoot, char *szName, void *pValue, int nType) //配置文件读取 { FILE *fp; int nFlag = 0; char buf[1024], szRootExt[100], szNameExt[100]; assert( (fp = fopen(szPath, "r")) != NULL); sprintf(szRootExt, "[%s]", szRoot); sprintf(szNameExt, "%s=", szName); while (feof(fp) == 0) { memset(buf, 0, sizeof(buf)); fgets(buf, sizeof(buf), fp); if (buf[0] == '#') continue; if (nFlag == 0 && buf[0] != '[') continue; else if (nFlag == 0 && buf[0] == '[') { if (strncmp(buf, szRootExt, strlen(szRootExt)) == 0) nFlag = 1; } else if (nFlag == 1 && buf[0] == '[') { break; } else { if (strncmp(buf, szNameExt, strlen(szNameExt)) == 0) { assert(GetConfigStrValue(buf, pValue, nType) == 0); fclose(fp); return 0; } } } fclose(fp); return -1; } int main() { int nNumber, i, nPort; char szRoot[100], szIP[100]; assert( GetConfigValue("./config.ini", "SERVER", "NUM", &nNumber, STRINT)==0 ); cout << "No. = " << nNumber << endl; for( i=0; i<nNumber; i++ ) { sprintf(szRoot, "SERVER%d", i+1); memset(szIP, 0, sizeof(szIP)); GetConfigValue("./config.ini", szRoot, "IP", szIP, STRSTR); GetConfigValue("./config.ini", szRoot, "PORT", &nPort, STRINT); cout << "SERVER" << i+1 << " IP-->" << szIP << " PORT-->" << nPort << endl; } return 0; }