1. printf
比如
char a = \x90;
printf("%02x", a);
想输出为90,没想到却是ffffff90,这个问题害我一个程序老是出错
最终发现只要改为
unsigned char a = \x90;
问题就解决了,其实还是正负数的问题
2. zlib
zlib unresolved external symbol _uncompress
inflate_fast崩溃
网上搜了一下,汇编版本的有坑
解决方法是编译zlib的时候用releasewithoutasm (Debug/Releasse那里选择)
这样生成的库是不崩溃的
3. socket TIME_WAIT
通信双方建立TCP连接后,主动关闭连接的一方会进入TIME_WAIT状态,一直占用端口号。设置socket属性可让其立即终止
Linux下
struct linger ling = {1, 0};
setsockopt(server_sockfd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
Windows下把上面参数都改为0就行了.
4. TCP长连接
对于TCP长连接保活是十分必要的,原因如下:
- 很多防火墙对一段时间内没有报文活动的socket会自动关闭。
- 对于非正常断开的连接系统并不能侦测到,比如防火墙关闭端口、网线被拔掉、电脑突然奔掉、未关闭应用程序直接关机(服务端无法释放资源)。(调用close(fd)为正常断开,连接对端可以侦测到)
TCP长连接保持的两种办法:
- 应用层面的心跳机制
自定义心跳消息头,一般客户端主动发送到服务端,服务器接收后进行回应(也可以不回应),以便能够侦测连接是否异常断开。 - TCP协议自带的保活功能
通过设置TCP keepalive的属性和发送底层心跳包的时间间隔。TCP keepalive是在底层定时发送心跳报文,服务器端接收到底层的心跳报文直接丢弃,不关心其内容。代码如下:
/*代码转自http://blog.csdn.net/embedded_sky/article/details/42077321*/
/*@author super bert 2014-12-16*/
/*socket TCP保持长连接函数*/
int socket_tcp_alive(int socket)
{
int ret = 0;
int keep_alive = 1;
ret = setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&keep_alive, sizeof(keep_alive));
if (ret == SOCKET_ERROR)
{
printf("setsockopt failed: %d \n", WSAGetLastError());
return -1;
}
struct tcp_keepalive in_keep_alive = {0};
unsigned long ul_in_len = sizeof(struct tcp_keepalive);
struct tcp_keepalive out_keep_alive = {0};
unsigned long ul_out_len = sizeof(struct tcp_keepalive);
unsigned long ul_bytes_return = 0;
in_keep_alive.onoff = 1; /*打开keepalive*/
in_keep_alive.keepaliveinterval = 5000; /*发送keepalive心跳时间间隔-单位为毫秒*/
in_keep_alive.keepalivetime = 1000; /*多长时间没有报文开始发送keepalive心跳包-单位为毫秒*/
ret = WSAIoctl(socket, SIO_KEEPALIVE_VALS, (LPVOID)&in_keep_alive, ul_in_len,
(LPVOID)&out_keep_alive, ul_out_len, &ul_bytes_return, NULL, NULL);
if (ret == SOCKET_ERROR)
{
printf("WSAIoctl failed: %d \n", WSAGetLastError());
return -1;
}
return 0;
}
5. getopt
处理命令行参数的一个函数
"a:b:cd::e"
,这就是一个选项字符串。对应到命令行就是-a ,-b ,-c ,-d, -e 。冒号又是什么呢? 冒号表示参数,一个冒号就表示这个选项后面必须带有参数(没有带参数会报错哦),但是这个参数可以和选项连在一起写,也可以用空格隔开,比如-a123 和-a 123(中间有空格) 都表示123是-a的参数;两个冒号的就表示这个选项的参数是可选的,即可以有参数,也可以没有参数,但要注意有参数时,参数与选项之间不能有空格(有空格会报错的哦),这一点和一个冒号时是有区别的。
大致处理代码如下:
while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Qv")) > 0)
switch (opt) {
case 'i': /* input dir */
in_dir = optarg;
break;
case 'o': /* output dir */
out_dir = optarg;
break;
default:
usage(argv[0]);
}
}