遍历目录 |
|
|
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
void listdir( char *path )
{
DIR *dp;
struct dirent *entry;
char childpath[512] = {};
// 目录是否存在
if((dp = opendir(path)) == NULL)
return;
// 目录列表
while( (entry = readdir(dp)) != NULL )
{
if( entry->d_type & DT_DIR ) // dir
{
// 过滤,防止死循环
if(strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0)
continue;
// 子目录绝对路径
sprintf( childpath,"%s/%s",path,entry->d_name );
// 递归
listdir(childpath);
}
else // file
{
printf("%s/%s\n",path,entry->d_name);
}
}
closedir(dp);
}
int main(int argc,char **argv)
{
listdir("/home/smart_push");
return 0;
}
|
hash_map |
hash_map |
|
#include <ext/hash_map> // hash_map
#include <map> // map
using namespace std;
// hash_map不是标准C++一部分,必须使用该命名空间才能使用
using namespace __gnu_cxx;
namespace __gnu_cxx
{
template<>
struct hash<string>
{
// 对于对象或结构体类型,hash_map必须实现()运算符,而map无此限制
size_t operator()(const string &s) const
{
return __stl_hash_string( s.c_str() );
}
};
}
/**
* @brief hash_map使用哈希表储存数据,算法复杂度为O(1)(最快情况为O(n)),查找速度比map快
*/
void test_hashmap()
{
// 基本类型
hash_map<int,int> hash;
hash[1] = 2; // []操作符
hash.insert( pair<int,int>(2,4) ); // pair方式
hash.insert( make_pair(3,8) );
(void)hash.size();
// string作值
hash_map<int,string> shash;
shash[1] = "world";
hash_map<int,string>::iterator it = shash.find(1); // 指针
string k = it->second;
hash_map<const char*,string> chash;
chash["hello"] = "world";
// string作键值时比较特殊
hash_map<string,string> sthash;
//sthash["hello"] = "world";
sthash.insert( make_pair(string("hello"),string("world")) );
// map
map<string,string> mp;
mp["hello"] = "world";
}
|
十六进制 |
tohex |
|
/**
* 字符串转化为16进制
*
*/
char *Str2Hex( const char *src,int count )
{
char *dest = new char[ 2*count + 1 ];
// 十六进制
for( int i=0; i<count; i++ )
{
// high
int h = ( src[i] >> 4 )&0x0f;
if( h <= 9 )
{
dest[i*2] = h + '0';
}
else
{
dest[i*2] = 'a' + h - 10;
}
// low
int l = src[i]&0x0f;
if( l <= 9 )
{
dest[i*2+1] = l + '0';
}
else
{
dest[i*2+1] = 'a' + l - 10;
}
}
dest[ count*2 ] = '\0';
return dest;
}
|
校验和计算 |
checksum |
|
/**
* @brief 自动计算IP包的校验和,包括TCP部分或UDP部分。添加伪IP头部
*
*/
int IPCheckSum( IP_HEADER* ip )
{
if( NULL==ip || 4!=ip->Version || 5 > ip->HeadLen )
{
return 1;
}
unsigned char protocol = ip->Protocol;
if (!(protocol==PROTOCOL_TCP || protocol==PROTOCOL_UDP))
{
ip->CheckSum = 0;
ip->CheckSum = CheckSum((unsigned short*)ip, sizeof(IP_HEADER));
return 1;
}
// 计算伪首部
char* ipdata = (char*)ip + ip->HeadLen*4;
CheckSumHeader* check = (CheckSumHeader*)(ipdata - sizeof(CheckSumHeader));
// temp备份原数据
char temp[sizeof(CheckSumHeader)];
memcpy(temp, check, sizeof(CheckSumHeader));
check->SrcIP = ip->SrcIP;
check->DestIP = ip->DestIP;
check->Zero = 0;
check->Protocol = protocol;
check->Length = htons(ntohs(ip->Length) - sizeof(IP_HEADER));
// 计算添加伪IP头部后校验和
if (protocol == PROTOCOL_TCP)
{
TCP_HEADER* tcp = (TCP_HEADER*)ipdata;
tcp->CheckSum = 0;
tcp->CheckSum = CheckSum((unsigned short*)check,
ntohs(ip->Length) - sizeof(IP_HEADER) + sizeof(CheckSumHeader));
}
else if (protocol == PROTOCOL_UDP)
{
UDP_HEADER* udp = (UDP_HEADER*)ipdata;
udp->CheckSum = 0;
udp->CheckSum = CheckSum((unsigned short*)check,
ntohs(ip->Length) - sizeof(IP_HEADER) + sizeof(CheckSumHeader));
}
// 恢复先前数据
memcpy( check, temp, sizeof(CheckSumHeader) );
// 计算IP校验和
ip->CheckSum = 0;
ip->CheckSum = CheckSum((unsigned short*)ip, sizeof(IP_HEADER));
return 0;
}
|
定时器 |
timerfd |
|
#include <unistd.h>
#include <stdio.h>
#include <sys/timerfd.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/epoll.h>
int createTimer()
{
// 建立定时器
int timer_id = timerfd_create( CLOCK_REALTIME,0 );
struct itimerspec interval = {0};
interval.it_value.tv_sec = 2;
interval.it_value.tv_nsec = 0;
interval.it_interval.tv_sec = interval.it_value.tv_sec;
interval.it_interval.tv_nsec = interval.it_value.tv_nsec;
// 设置触发时间间隔
timerfd_settime(timer_id, 0, &interval, NULL);
return timer_id;
}
void addTimer( int epfd,int timer_id )
{
struct epoll_event ev;
ev.data.fd = timer_id;
ev.events = EPOLLIN | EPOLLET;
epoll_ctl (epfd, EPOLL_CTL_ADD, timer_id, &ev);
}
void delTimer( int epfd,int timer_id )
{
struct epoll_event ev;
ev.data.fd = timer_id;
ev.events = EPOLLIN | EPOLLET;
epoll_ctl (epfd, EPOLL_CTL_DEL, timer_id, &ev);
}
void *thread_fun( void *arg )
{
char buf[100] = {0};
while(1)
{
struct epoll_event events[5] ={0};
int nfds = epoll_wait(epfd, events, 5, -1);
int i;
for(i=0;i<nfds;i++)
{
if( read( events[i].data.fd,buf,100 ) > 0 )
{
// 执行定时器回调函数
printf("%d %s\n",events[i].data.fd,"hello callback"); // buf = 3
}
}
}
return NULL;
}
/**
* @brief timerfd_create() 与 epoll() 配置使用示例
* 该接口基于文件描述符,通过文件可读事件进行超时通知,能被用于select/poll场景
* 1.新建定时器 2.设置触发时间 3.添加至epoll事件 4.epoll扫描
*/
int main(int arg,char **argv)
{
// 扫描epoll事件
pthread_t tid;
pthread_create(&tid, NULL, thread_fun, NULL);
// 配合timer使用
int epfd = epoll_create(5);
// 添加定时器
int timer_id = createTimer();
addTimer(timer_id);
pause();
return 0;
}
|
同步障碍 |
barrier |
|
#ifndef _KCODE_BARRIER_H
#define _KCODE_BARRIER_H
/**
* pthread_barrier_t 实现源码
*/
#include <pthread.h>
#include <stdlib.h>
#define KBARRIER_SERIAL_THREAD -1
typedef struct _kbarrier
{
pthread_mutex_t m;
pthread_cond_t cond;
unsigned int cnt;
}kbarrier,*kbarrier_t;
/// 初始化
int kbarrier_init(kbarrier_t b,unsigned int cnt)
{
kbarrier_t barrier = (kbarrier_t)malloc(sizeof(struct kbarrier));
pthread_mutex_init(&barrier->m,NULL);
pthread_cond_init(&barrier->cond,NULL);
barrier->cnt = cnt;
b = barrier;
return 0;
}
/// 清理
int kbarrier_destroy(kbarrier_t b)
{
pthread_mutext_destroy(&b->m);
pthread_cond_destroy(&b->cond);
free(b);
return 0;
}
/// 计数
int kbarrier_wait(kbarrier_t b)
{
kbarrier *impl = b;
pthread_mutex_lock(&impl->m);
impl->cnt--;
if(impl->cnt ==0)
{
pthread_mutex_unlock(&impl->m);
pthread_cond_broadcast(&impl->cond); // 唤醒所有的线程
return KBARRIER_SERIAL_THREAD;
}
// 线程等待
pthread_cond_wait(&impl->cond);
pthread_mutex_unlock(&impl->m);
return 0;
}
#endif
|
工具代码 |
mixture |
|
/// 获取系统当时时间
static void GetTime()
{
time_t rawTime;
struct tm *tminfo;
time(&rawTime);
tminfo = localtime(&rawTime); // 获取当前系统时间,相当于 QDateTime::currentDateTime().toTime_t();
// strftime格式化
char buffer[80];
strftime(buffer,80,"时间:%Y-%m-%d %H:%M:%S",tminfo);
// 拼凑时间字符串
printf("当前时间串:%04d-%02d-%02d %02d:%02d:%02d\n",
tminfo->tm_year+1900,tminfo->tm_mon+1,tminfo->tm_mday,
tminfo->tm_hour,tminfo->tm_min,tminfo->tm_sec);
}
/// memcpy实现,考虑到内存重叠的问题。更简单的方式,从后面往前面拷贝
void* my_memcpy(void *dst,void *src,size_t count)
{
assert(dst!=NULL);
assert(src!=NULL);
void *dest = dst;
if(dst<src||(char*)dst>((char*)src+count)) // 内存不重叠
{
while(count--)
{
*(char*)dst = *(char*)src; // 赋值
dst = (char*)dst + 1;
src = (char*)src +1;
}
}else // 内存重叠,从高位向低位拷贝
{
dst = (char*)dst + count-1; // 定位到最高位
src = (char*)src + count-1;
while(count--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst -1;
src = (char*)src -1;
}
}
return dest;
}
/// 动态库加载
#ifdef WIN32
#include <windows.h>
#else
#include <dlfcn.h> // -ldl
#endif
typedef void (*ShowMsg)();
static void LoadLibrary()
{
#ifdef WIN32
HINSTANCE bDllInst=LoadLibrary("test.dll");
if(bDllInst)
{
ShowMsg pMsg=(ShowMsg)GetProcAddress(bDllInst,"showMsg");
if(pMsg)
{
pMsg();
}
}
FreeLibrary(bDllInst);
#else
void *libHandle=dlopen("libtest.so",RTLD_LAZY);
assert(libHandle != NULL);
ShowMsg pMsg=dlsym(libHandle,"showMsg");
if(pMsg)
{
pMsg();
}
dlclose(libHandle);
#endif
}
|
消息队列 |
msg |
|
// msgsend.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#define MSGKEY 1024
typedef struct _msgstu
{
long msgtype;
char msgtxt[2048];
}msgstu;
int main()
{
struct msgstu msgs;
int ret;
int msgid;
msgid = msgget(MSGKEY,IPC_CREAT|0666);
assert(msgid != -1);
msgs.msgtype = 11;
strcpy(msgs.msgtxt,"hello world");
// 发送
ret=msgsnd(msgid,&msgs,sizeof(struct msgstu),IPC_NOWAIT);
assert( ret != -1 );
// 删除
msgctl(msgid,IPC_RMID,0);
return 0;
}
// msgrecv.c
int main()
{
// 检测消息是否存在
int msgid = msgget(MSGKEY,IPC_EXCL);
assert(msgid != -1);
ret=msgrcv(msgid,&msgs,sizeof(struct msgstu),0,0);
printf("msg:%d %s\n",msgs.msgtype,msgs.msgtxt);
return 0;
}
|
管道通信 |
pipe |
|
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
/**
* @brief 单向管道,定义 O_RDWR 模式引起代码行为不可预知
* /tmp/my_fifo
*/
int main(int argc,char **argv)
{
int pipe_fd;
char buffer[1024];
strcpy(buffer,"hello world");
// 管道文件不存在,则新建
if(access(fifo_name,F_OK)==-1)
{
if(mkfifo (fifo_name,0777)!=0)
{
perror("mkfifo");
return -1;
}
}
// 堵塞
pipe_fd = open("/tmp/my_fifo",O_WRONLY);
assert(pipe_fd != -1);
write(pipe_fd,buffer,strlen(buffer));
return 0;
}
/**
*@brief 非堵塞方式操作FIFO文件
*/
int main(int argc,char **argv)
{
int pipe_fd;
char buffer[PIPE_BUF+1] = {};
// 堵塞
if((pipe_fd = open("/tmp/my_fifo",O_RDONLY))==-1)
{
perror("open");
return -1;
}
// 向管道写消息
read(pipe_fd,buffer,PIPE_BUF);
printf("recv:%s\n",buffer);
close(pipe_fd);
return 0;
}
|