类别归档:Web开发

RSS feed of Web开发

最后更新于 .

最近需要上线的逻辑server由于需要与大量的后台server交互,今天突然发现有大量的close_wait产生,于是仔细研究了一下:
首先我们知道,如果我们的服务器程序处于CLOSE_WAIT状态的话,说明套接字是被动关闭的!
因为如果是CLIENT端主动断掉当前连接的话,那么双方关闭这个TCP连接共需要四个packet:

Client ---> FIN  ---> Server
Client <--- ACK  <--- Server


这时候Client端处于FIN_WAIT_2状态;而Server 程序处于CLOSE_WAIT状态。

Client <--- FIN  <--- Server


这时Server 发送FIN给Client,Server 就置为LAST_ACK状态。

Client ---> ACK  ---> Server


Client回应了ACK,那么Server 的套接字才会真正置为CLOSED状态。

Server 程序处于CLOSE_WAIT状态,而不是LAST_ACK状态,说明还没有发FIN给Client,那么可能是在关闭连接之前还有许多数据要发送或者其他事要做,导致没有发这个FIN packet。
通常来说,一个CLOSE_WAIT会维持至少2个小时的时间(这个时间外网服务器通常会做调整,要不然太危险了)。如果有个流氓特地写了个程序,给你造成一堆的CLOSE_WAIT,消耗
你的资源,那么通常是等不到释放那一刻,系统就已经解决崩溃了 ...

最后更新于 .

这几天在写一个server,由于框架相同,仅仅是获取数据源的地方有区别,所以,研究了一下如何使用面向对象的方法来动态加载so。

主要思想就是:
1.通过一个函数能够获得一个基类的指针,这样在调用基类的函数的时候,就能自动调用子类的实现了。
2.存储so对象的指针应该是外层类的一个static变量。

详细还是看代码吧:
1)首先定义一个公共的头文件,里面存储的基类的定义:(需要注意的就是,只要不是纯虚函数,那么就一定要有实现;还有就是析构函数需要为虚函数)
so和主调程序都需要包含这个头文件。
source_base.h

#ifndef _SOURCE_BASE_H_
#define _SOURCE_BASE_H_
#include <iostream>
using namespace std;
class CSourceBase;
/** 
 * @brief    获取实例
 * 
 * @param    client        new出的指针
 * 
 * @return    0            succ
 *             else        fail
 */
extern “C” int CreatObj(CSourceBase *& client);
class CSourceBase
{
    public:
        CSourceBase ...

最后更新于 .

如何保证一个程序在单台服务器上只有唯一实例呢,本着简单实用的思想写了一个实现函数:

/* 判断当前进程是否已经运行 */
static bool is_running(const char* prg)
{
    const char* pid_file = ".tmp_pid";
    const char* p = strrchr(prg, '/');
    if (p)
    {
        p++;
    }
    else
    {
        p = prg;
    }
    char cmd[128] = {0};
    sprintf(cmd, "pgrep %s >%s", p, pid_file);
    system(cmd);
    std::string s;
    FILE* fp = fopen(pid_file, "r");
    if (fp == NULL)
    {
        fprintf(stderr, "ERROR: can not open ...

最后更新于 .

给第三方提供接口的时候,设计了一个传入大量id的接口,结果昨天测试发现,传入了100个ID,结果只返回55个的数据,一开始以为是API有问题,后台调试才发现,原来是URL自己截断了!
后来仔细了解了一下,原来通过GET方式请求,并传递一个过长的参数的话,IE会自动的截去超出最大长度的字符。
微软的权威解释,IE的url最大长度是2083个字节,可以用于GET传递数据的长度是2048个字节。
Maximum URL length is 2,083 characters in Internet Explorer.
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q208427

其实也比较容易解决,只要换成post请求就可以了。

转载请注明出处.https://www.vimer.cn

最后更新于 .

其实在认真阅读了这篇名为“计算内存使用”的文章之后,还是处于半迷糊状态。这位作者就说Linux下面没有特别好的显示内存占用的工具,虽然有top和free,但都说得不清楚,就跟巫毒教的魔术似的。 比如top这个工具,它会显示3种数据,作者分别解释如下:

VIRT:virtual memory usage。Virtual这个词很神,一般解释是:virtual adj.虚的, 实质的, [物]有效的, 事实上的。到底是虚的还是实的?让Google给Define之后,将就明白一点,就是这东西还是非物质的,但是有效果的,不发生在真实世界的,发生在软件世界的等等。这个内存使用就是一个应用占有的地址空间,只是要应用程序要求的,就全算在这里,而不管它真的用了没有。写程序怕出错,又不在乎占用的时候,多开点内存也是很正常的。
RES:resident memory usage。常驻内存。这个值就是该应用程序真的使用的内存,但还有两个小问题,一是有些东西可能放在交换盘上了(SWAP),二是有些内存可能是共享的。
SHR:shared memory。共享内存。就是说这一块内存空间有可能也被其他应用程序使用着;而Virt - Shr似乎就是这个程序所要求的并且没有共享的内存空间 ...

最后更新于 .

这周一台新server要上线,突然想起用的是短链接,而且是client端主动断链接,于是就

netstat -lan

看了一下,果然发现大量的TIME_WAIT(9000左右),即系统在发现客户端断掉链接之后的等待状态,解决方法就是打开机器的快速回收。
命令如下:

cd /proc/sys/net/ipv4 
echo 1 > tcp_tw_recycle

过几分钟,在用netstat看一下,果然降到了100左右~~

如果,没有开快速回收就上外网……,结果可以想象了……

 

最后更新于 .

最近项目小组在去除代码中的warning,在修正代码的过程中看到了对结构体不正确的初始化方式:
假设有一个如下的struct定义:

struct astruct
{
    int a;
    int b;
};
struct astruct test = {0};

即使astruct中都是基础类型的成员这样的初始化话也是不正确的。
这种初始化仅仅是把a变量设置为了0,而未对b变量做初始化。
产生这样错误的原因,大概是收到数组初始化的影响。数组是可以这么初始化话的,而且初始化的值只能是0!
对结构体的初始化,可以有一下三种。

struct test
{
    int a;
    int b;
};
int main()
{
    struct test t1 = {0, 0}; 
    struct test t2 = { 
        .a=2, 
        .b=3
    };  
    struct test t3 = { 
        a:12345,
        b:567890
    };  
    printf("t1.a = %d, t1.b ...

最后更新于 .

Linux进程管理命令详解(ps和top)
1.ps命令
作用:ps命令主要查看系统中进程的状态。
格式:ps [选项]
主要选项如下。

-A:显示系统中所有进程的信息。
-e:显示所有进程的信息。
-f:显示进程的所有信息。
-l:以长格式显示进程信息。
-r:只显示正在运行的进程。
-u:显示面向用户的格式(包括用户名、CPU及内存使用情况等信息)。
-x:显示所有非控制终端上的进程信息。
-p:显示由进程ID指定的进程的信息。
-t:显示指定终端上的进程的信息。

说明:要对进程进行监测和控制,首先要了解当前进程的情况,也就是需要查看当前进程。ps命令就是最基本、也是非常强大的进程查看命令。根据显示的信息可以确定哪个进程正在运行、哪个进程被挂起、进程已运行了多久、进程正在使用的资源、进程的相对优先级,以及进程的标志号(PID)。所有这些信息对用户都很有用,对于系统管理员来说更为重要。使用”ps -aux”命令可以获得终端上所有用户的有关进程的所有信息,下面结合图讲解进程的基本信息。

130727331

图中第二行代码中,USER表示启动进程用户。PID表示进程标志号。%CPU表示运行该进程占用CPU的时间与该进程总的运行时间的比例。%MEM表示该进程占用内存和总内存的比例。VSZ表示占用的虚拟内存大小,以KB为单位 ...

最后更新于 .

一.关于gdb调试core文件总是一堆问号的问题
问题描述:已经在编译选项中加入了-g,但是查看core文件时,还是一堆问号,使用的命令为:

gdb -c core

解决方案:由于gdb -c core这样的使用在有些系统下支持不是很好,所以推荐用如下两种方法:

1)gdb exe

(gdb) core-file core

2)gdb -c core

(gdb) file exe

而其中第二种方法在某些系统上也是不好用的,所以就用第一种即可。

二.回滚svn版本
今天很无聊的改代码,结果把正确的版本给修改掉了,因为实在linux终端上,没有图形界面的svn,所以只能用命令……

首先保证我们拿到的是最新代码,运行svn up,发现目前是29118版本。 然后找出要撤销的确切版本:

svn log spp_xyserver.cpp

根据log发现前面一个版本是29062,比较一下:

svn diff -r 29062 ...

最后更新于 .

查看错误代码errno是调试程序的一个重要方法。当linuc C api函数发生异常时,一般会将errno变量(需include errno.h)赋一个整数值, 不同的值表示不同的含义,可以通过查看该值推测出错的原因。在实际编程中用这一招解决了不少原本看来莫名其妙的问题。比较麻烦的是每次都要去linux源代码里面查找错误代码的含义,现在把它贴出来,以后需要查时就来这里看了。
以下来自linux 的内核代码中的/usr/include/asm/errno.h


#ifndef _I386_ERRNO_H
#define _I386_ERRNO_H
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 ...