69,512
社区成员
![](https://csdnimg.cn/release/cmsfe/public/img/topic.427195d5.png)
![](https://csdnimg.cn/release/cmsfe/public/img/me.40a70ab0.png)
![](https://csdnimg.cn/release/cmsfe/public/img/task.87b52881.png)
![](https://csdnimg.cn/release/cmsfe/public/img/share-circle.3e0b7822.png)
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
//日志目录 & 日志命名格式
#define LOG_DIR "log/"
#define LOG_FILE_TEMPLATE "%s%04d-%02d-%02d.log"
uint64_t varint_unpack_fordata(char* data) {
uint64_t outint = 0;
uint8_t tmp;
size_t i = 0;
while (1) {
tmp = (uint8_t)data[i];
outint |= (uint64_t)(tmp & 0x7F) << (7 * i);
if (!(tmp & 0x80)) {
break;
}
i++;
if (i > 9) {
return -1;
}
}
return outint;
}
struct VarintPack {
uint8_t* value;
size_t byte_length;
};
struct VarintPack varint_pack(uint64_t number) {
struct VarintPack result = {NULL, 0};
uint8_t buffer[10];
uint8_t* ptr = buffer;
while (number != 0) {
uint8_t tmp = number & 0x7F;
number >>= 7;
if (result.byte_length > 0 || number != 0) {
tmp |= 0x80;
}
*ptr++ = tmp;
++result.byte_length;
}
result.value = malloc(result.byte_length);
memcpy(result.value, buffer, result.byte_length);
return result;
}
void socket_log(const char* level, const char* format, ...) {
if(level == "test" && 1 == 0){
return;
}
time_t now = time(NULL);
struct tm *local_time = localtime(&now);
char log_file_name[100];
snprintf(log_file_name, sizeof(log_file_name), LOG_FILE_TEMPLATE, LOG_DIR, local_time->tm_year + 1900, local_time->tm_mon + 1, local_time->tm_mday);
FILE* log_file = fopen(log_file_name, "a");
if (log_file == NULL) {
perror("Failed to open log file");
return;
}
char timestamp[30];
strftime(timestamp, sizeof(timestamp), "[%H:%M:%S] ", local_time);
va_list args;
va_start(args, format);
char buffer[512];
vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
fprintf(log_file, "[%s] %s%s\n", level, timestamp, buffer);
fclose(log_file);
}
int main() {
char jsondata[] = "{\"version\":{\"name\":\"1.19.4\",\"protocol\":762 },\"players\":{\"max\":100,\"online\":5,\"sample\":[{\"name\":\"thinkofdeath\",\"id\":\"4566e69f-c907-48ee-8d71-d7ba5aa00d20\"}]},\"description\":{\"text\":\"Hello world\"},\"favicon\":\"data:image/png;base64,<data>\",\"enforcesSecureChat\":true,\"previewsChat\":true }";
int json_length = strlen(jsondata);
uint8_t buffer[512 + json_length];
//socket_log("test", "##发送数据长度:%d",json_length);
printf("%d",json_length);
struct VarintPack varint_encoded = varint_pack(json_length);
memcpy(buffer, &varint_encoded.value, varint_encoded.byte_length);
memcpy(buffer + varint_encoded.byte_length, jsondata, json_length);
int data2 = varint_unpack_fordata((char*)varint_encoded.value);
socket_log("test", "发送数据长度:%d",data2);
if ((uint32_t)json_length == data2) {
printf("Varint pack and unpack successful. Original: %u, Unpacked: %lu\n", json_length, data2);
} else {
printf("Varint pack and unpack failed. Original: %u, Unpacked: %lu\n", json_length, data2);
}
}
注释的那行代码
//socket_log("test", "##发送数据长度:%d",json_length);
这句如果被注释,结果是:
282Varint pack and unpack successful. Original: 282, Unpacked: 282
是正确的。
然而如果取消掉注释,结果是:
282Varint pack and unpack failed. Original: 282, Unpacked: 796541210
是错误的,并且每次运行Unpacked的值都会发生变化。
求大佬指点一下。
这就是代码能跑就不要动吗。
问了AI,AI没看出来问题。
我也用了网上的代码在线运行工具,发现并不是我电脑的问题。
仅供参考:
//循环向a函数每次发送200个字节长度(这个是固定的)的buffer,
//a函数中需要将循环传进来的buffer,组成240字节(也是固定的)的新buffer进行处理,
//在处理的时候每次从新buffer中取两个字节打印
#ifdef _MSC_VER
#pragma warning(disable:4996)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER
#include <windows.h>
#include <process.h>
#include <io.h>
#define MYVOID void
#define vsnprintf _vsnprintf
#else
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#define CRITICAL_SECTION pthread_mutex_t
#define MYVOID void *
#endif
//Log{
#define MAXLOGSIZE 20000000
#define MAXLINSIZE 16000
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
static char logstr[MAXLINSIZE+1];
char datestr[16];
char timestr[16];
char mss[4];
CRITICAL_SECTION cs_log;
FILE *flog;
#ifdef _MSC_VER
void Lock(CRITICAL_SECTION *l) {
EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
LeaveCriticalSection(l);
}
void sleep_ms(int ms) {
Sleep(ms);
}
#else
void Lock(CRITICAL_SECTION *l) {
pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
pthread_mutex_unlock(l);
}
void sleep_ms(int ms) {
usleep(ms*1000);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
struct tm *now;
struct timeb tb;
if (NULL==pszFmt||0==pszFmt[0]) return;
vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);
ftime(&tb);
now=localtime(&tb.time);
sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
sprintf(timestr,"%02d:%02d:%02d",now->tm_hour ,now->tm_min ,now->tm_sec );
sprintf(mss,"%03d",tb.millitm);
printf("%s %s.%s %s",datestr,timestr,mss,logstr);
flog=fopen(logfilename1,"a");
if (NULL!=flog) {
fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);
if (ftell(flog)>MAXLOGSIZE) {
fclose(flog);
if (rename(logfilename1,logfilename2)) {
remove(logfilename2);
rename(logfilename1,logfilename2);
}
} else {
fclose(flog);
}
}
}
void Log(const char *pszFmt,...) {
va_list argp;
Lock(&cs_log);
va_start(argp,pszFmt);
LogV(pszFmt,argp);
va_end(argp);
Unlock(&cs_log);
}
//Log}
#define ASIZE 200
#define BSIZE 240
#define CSIZE 2
char Abuf[ASIZE];
char Cbuf[CSIZE];
CRITICAL_SECTION cs_HEX;
CRITICAL_SECTION cs_BBB;
struct FIFO_BUFFER {
int head;
int tail;
int size;
char data[BSIZE];
} BBB;
int No_Loop=0;
void HexDump(int cn,char *buf,int len) {
int i,j,k;
char binstr[80];
Lock(&cs_HEX);
for (i=0;i<len;i++) {
if (0==(i%16)) {
sprintf(binstr,"%03d %04x -",cn,i);
sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
} else if (15==(i%16)) {
sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
sprintf(binstr,"%s ",binstr);
for (j=i-15;j<=i;j++) {
sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
}
Log("%s\n",binstr);
} else {
sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
}
}
if (0!=(i%16)) {
k=16-(i%16);
for (j=0;j<k;j++) {
sprintf(binstr,"%s ",binstr);
}
sprintf(binstr,"%s ",binstr);
k=16-k;
for (j=i-k;j<i;j++) {
sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
}
Log("%s\n",binstr);
}
Unlock(&cs_HEX);
}
int GetFromRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) {
int lent,len1,len2;
lent=0;
Lock(cs);
if (fbuf->size>=len) {
lent=len;
if (fbuf->head+lent>BSIZE) {
len1=BSIZE-fbuf->head;
memcpy(buf ,fbuf->data+fbuf->head,len1);
len2=lent-len1;
memcpy(buf+len1,fbuf->data ,len2);
fbuf->head=len2;
} else {
memcpy(buf ,fbuf->data+fbuf->head,lent);
fbuf->head+=lent;
}
fbuf->size-=lent;
}
Unlock(cs);
return lent;
}
MYVOID thdB(void *pcn) {
char *recv_buf;
int recv_nbytes;
int cn;
int wc;
int pb;
cn=(int)pcn;
Log("%03d thdB thread begin...\n",cn);
while (1) {
sleep_ms(10);
recv_buf=(char *)Cbuf;
recv_nbytes=CSIZE;
wc=0;
while (1) {
pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);
if (pb) {
Log("%03d recv %d bytes\n",cn,pb);
HexDump(cn,recv_buf,pb);
sleep_ms(1);
} else {
sleep_ms(1000);
}
if (No_Loop) break;//
wc++;
if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);
}
if (No_Loop) break;//
}
#ifndef _MSC_VER
pthread_exit(NULL);
#endif
}
int PutToRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) {
int lent,len1,len2;
Lock(cs);
lent=len;
if (fbuf->size+lent>BSIZE) {
lent=BSIZE-fbuf->size;
}
if (fbuf->tail+lent>BSIZE) {
len1=BSIZE-fbuf->tail;
memcpy(fbuf->data+fbuf->tail,buf ,len1);
len2=lent-len1;
memcpy(fbuf->data ,buf+len1,len2);
fbuf->tail=len2;
} else {
memcpy(fbuf->data+fbuf->tail,buf ,lent);
fbuf->tail+=lent;
}
fbuf->size+=lent;
Unlock(cs);
return lent;
}
MYVOID thdA(void *pcn) {
char *send_buf;
int send_nbytes;
int cn;
int wc;
int a;
int pa;
cn=(int)pcn;
Log("%03d thdA thread begin...\n",cn);
a=0;
while (1) {
sleep_ms(100);
memset(Abuf,a,ASIZE);
a=(a+1)%256;
if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop
send_buf=(char *)Abuf;
send_nbytes=ASIZE;
Log("%03d sending %d bytes\n",cn,send_nbytes);
HexDump(cn,send_buf,send_nbytes);
wc=0;
while (1) {
pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);
Log("%03d sent %d bytes\n",cn,pa);
HexDump(cn,send_buf,pa);
send_buf+=pa;
send_nbytes-=pa;
if (send_nbytes<=0) break;//
sleep_ms(1000);
if (No_Loop) break;//
wc++;
if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);
}
if (No_Loop) break;//
}
#ifndef _MSC_VER
pthread_exit(NULL);
#endif
}
int main() {
#ifdef _MSC_VER
InitializeCriticalSection(&cs_log);
InitializeCriticalSection(&cs_HEX);
InitializeCriticalSection(&cs_BBB);
#else
pthread_t threads[2];
int threadsN;
int rc;
pthread_mutex_init(&cs_log,NULL);
pthread_mutex_init(&cs_HEX,NULL);
pthread_mutex_init(&cs_BBB,NULL);
#endif
Log("Start===========================================================\n");
BBB.head=0;
BBB.tail=0;
BBB.size=0;
#ifdef _MSC_VER
_beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);
_beginthread((void(__cdecl *)(void *))thdB,0,(void *)2);
#else
threadsN=0;
rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
#endif
if (!access("No_Loop",0)) {
remove("No_Loop");
if (!access("No_Loop",0)) {
No_Loop=1;
}
}
while (1) {
sleep_ms(1000);
if (No_Loop) break;//
if (!access("No_Loop",0)) {
No_Loop=1;
}
}
sleep_ms(3000);
Log("End=============================================================\n");
#ifdef _MSC_VER
DeleteCriticalSection(&cs_BBB);
DeleteCriticalSection(&cs_HEX);
DeleteCriticalSection(&cs_log);
#else
pthread_mutex_destroy(&cs_BBB);
pthread_mutex_destroy(&cs_HEX);
pthread_mutex_destroy(&cs_log);
#endif
return 0;
}
根因是result.value尾部未补充'\0',多执行socket_log,会造成栈内存存在脏数据导致。
可按照我的修改尝试下:
您也看出来是因为socket_log函数的struct tm *local_time = localtime(&now)这句代码引发的问题。我又试了其他获取日期的方法,比如ctime(),也不行。但是time_t now = time(NULL)获取1970年至今的秒数却没问题,所以我就想通过秒数自己来计算年月日时分秒。代码就改了socket_log函数:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
//日志目录 & 日志命名格式
#define LOG_DIR "log/"
#define LOG_FILE_TEMPLATE "%s%04d-%02d-%02d.log"
uint64_t varint_unpack_fordata(char* data) {
uint64_t outint = 0;
uint8_t tmp;
size_t i = 0;
while (1) {
tmp = (uint8_t)data[i];
outint |= (uint64_t)(tmp & 0x7F) << (7 * i);
if (!(tmp & 0x80)) {
break;
}
i++;
if (i > 9) {
return -1;
}
}
return outint;
}
struct VarintPack {
uint8_t* value;
size_t byte_length;
};
struct VarintPack varint_pack(uint64_t number) {
struct VarintPack result = {NULL, 0};
uint8_t buffer[10];
uint8_t* ptr = buffer;
while (number != 0) {
uint8_t tmp = number & 0x7F;
number >>= 7;
if (result.byte_length > 0 || number != 0) {
tmp |= 0x80;
}
*ptr++ = tmp;
++result.byte_length;
}
result.value = malloc(result.byte_length);
memcpy(result.value, buffer, result.byte_length);
return result;
}
int IsRound(int year){
if((year%100)&&(year%4==0)) return 1;
if((year%100==0)&&(year%400==0)) return 1;
return 0;
}
void socket_log(const char* level, const char* format, ...) {
if(level == "test" && 1 == 0){
return;
}
time_t now = time(NULL);
time_t timep;
int n;
int year_s[2]= {365*24*60*60, 366*24*60*60};
int month_s[2][12]={{31,28,31,30,31,30,31,31,30,31,30,31},
{31,29,31,30,31,30,31,31,30,31,30,31}};
int day_s = 24*60*60;
int hour_s = 60*60;
int minute_s = 60;
n=time(&timep);
int temp = n;
int year=1970;
int month=1;
int day=1;
int hour=0;
int minute=0;
int second=0;
while(temp>=60){
int flag= IsRound(year);
if(temp>=year_s[flag]) { year++; temp-=year_s[flag]; }
else if(temp>=day_s){
int days = temp/day_s;
temp=temp%day_s;
int i=0;
int flag = IsRound(year);
int hh=31;
while(days>=hh){
days-=month_s[flag][i++];
hh=month_s[flag][i];
}
month+= i;
day+=days;
}else if(temp>=hour_s){
hour=temp/hour_s;
temp%=hour_s;
}else if(temp>=minute_s){
minute = temp/minute_s;
temp%=minute_s;
}
}
second = temp;
// struct tm *local_time = localtime(&now);
char log_file_name[100];
snprintf(log_file_name, sizeof(log_file_name), LOG_FILE_TEMPLATE, LOG_DIR, year, month, day);
FILE* log_file = fopen(log_file_name, "a");
if (log_file == NULL) {
perror("Failed to open log file");
return;
}
char timestamp[30];
sprintf(timestamp,"[%d:%d:%d]",hour,minute,second);
//strftime(timestamp, sizeof(timestamp), "[%H:%M:%S] ", local_time);
va_list args;
va_start(args, format);
char buffer[512];
vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
fprintf(log_file, "[%s] %s%s\n", level, timestamp, buffer);
fclose(log_file);
}
int main() {
char jsondata[] = "{\"version\":{\"name\":\"1.19.4\",\"protocol\":762 },\"players\":{\"max\":100,\"online\":5,\"sample\":[{\"name\":\"thinkofdeath\",\"id\":\"4566e69f-c907-48ee-8d71-d7ba5aa00d20\"}]},\"description\":{\"text\":\"Hello world\"},\"favicon\":\"data:image/png;base64,<data>\",\"enforcesSecureChat\":true,\"previewsChat\":true }";
int json_length = strlen(jsondata);
uint8_t buffer[512 + json_length];
socket_log("test", "##发送数据长度:%d",json_length);
printf("json_length:%d\n",json_length);
struct VarintPack varint_encoded = varint_pack(json_length);
memcpy(buffer, &varint_encoded.value, varint_encoded.byte_length);
memcpy(buffer + varint_encoded.byte_length, jsondata, json_length);
int data2 = varint_unpack_fordata((char*)varint_encoded.value);
socket_log("test", "发送数据长度:%d",data2);
if ((uint32_t)json_length == data2) {
printf("Varint pack and unpack successful. Original: %u, Unpacked: %lu\n", json_length, data2);
} else {
printf("Varint pack and unpack failed. Original: %u, Unpacked: %lu\n", json_length, data2);
}
}
结果:
数组越界了,51行result.value = malloc(result.byte_length)可以修改一下:
result.value = malloc(result.byte_length+1);
memset(result.value,0,result.byte_length+1);
第45行看上去不舒服。
我的回复怎么没了
if(level == "test"
这个比较应该用strcmp
有没有大佬救救我啊。
目前已知socket_log函数的:
struct tm *local_time = localtime(&now);
这一行存在时,varint_unpack_fordata函数的while循环会多循环几次,导致outint变得更长,表示的数变得更大。