喜欢FreeBSD

在FreeBSD中记下的


My Links

Blog Stats

随笔分类

随笔档案

文章档案

2008年7月22日 #

 
struct sockaddr {
       unsigned short sa_family; /* 地址族, AF_xxx */
       char sa_data[14]; /* 14字节的协议地址*/
   };
  
上面是通用的socket地址,具体到Internet socket,用下面的结构,二者可以进行类型转换
  
struct sockaddr_in {
       short int sin_family; /* 地址族 */
       unsigned short int sin_port; /* 端口号 */
       struct in_addr sin_addr; /* Internet地址 */
       unsigned char sin_zero[8]; /* 与struct sockaddr一样的长度 */
   };
  
   struct in_addr就是32位IP地址。
  
   struct in_addr {
       unsigned long s_addr;
   }; (这种好记)
也有
struct in_addr {  
      union {    
            struct { u_char s_b1,s_b2,s_b3,s_b4;} S_un_b;    
            struct { u_short s_w1,s_w2;} S_un_w;    
            u_long S_addr; 
      } S_un;
};

利用u_long htonl(u_long hostlong);将主机字节序转换为TCP/IP网络字节序.
利用u_short htons(u_short hostshort);将主机字节序转换为TCP/IP网络字节序.
inet_addr()是将一个点分制的IP地址(如192.168.0.1)转换为上述结构中需要的32位IP地址(0xC0A80001)。
 
通常的用法是:
int sockfd;
struct sockaddr_in my_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0); /* 做一些错误检查! */
my_addr.sin_family = AF_INET; /* 主机字节序 */
my_addr.sin_port = htons(MYPORT); /* short, 网络字节序 */
my_addr.sin_addr.s_addr = inet_addr("192.168.0.1");
bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */
/* 不要忘了为bind()做错误检查: */
bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
 
 
 
posted @ 2008-07-22 01:47 hihee的博客 阅读(50) | 评论 (0)编辑 收藏

inet_addr函数处理IP地址需要注意的问题
xuefeifei 发表于 2006-3-28 15:39:00
 
现在我们很幸运,因为我们有很多的函数来方便地操作 IP 地址。
没有 必要用手工计算它们,也没有必要用"<<"操作来储存成长整字型。
首先,假设你已经有了一个sockaddr_in结构体ina,你有一个IP地址"132.241.5.10" 要储存在其中,
你就要用到函数inet_addr(),将IP地址从 点数格式转换成无符号长整型。使用方法如下:
      ina.sin_addr.s_addr = inet_addr("132.241.5.10");
注意,inet_addr()返回的地址已经是网络字节格式,所以你无需再调用 函数htonl()。
我们现在发现上面的代码片断不是十分完整的,因为它没有错误检查。
显而易见,当inet_addr()发生错误时返回-1。记住这些二进制数字?(无符 号数)-1仅仅和IP地址255.255.255.255相符合!
这可是广播地址!大错特 错!记住要先进行错误检查。
好了,现在你可以将IP地址转换成长整型了。有没有其相反的方法呢? 它可以将一个in_addr结构体输出成点数格式?这样的话,你就要用到函数 inet_ntoa()("ntoa"的含义是"network to ascii"),就像这样:
printf("%s",inet_ntoa(ina.sin_addr));
它将输出IP地址。需要注意的是inet_ntoa()将结构体in-addr作为一 个参数,不是长整形。
同样需要注意的是它返回的是一个指向一个字符的 指针。它是一个由inet_ntoa()控制的静态的固定的指针,
所以每次调用 inet_ntoa(),它就将覆盖上次调用时所得的IP地址。例如:
     
       char *a1, *a2;
      a1 = inet_ntoa(ina1.sin_addr); /* 这是198.92.129.1 */
      a2 = inet_ntoa(ina2.sin_addr); /* 这是132.241.5.10 */
      printf("address 1: %s ",a1);
      printf("address 2: %s ",a2);
输出如下:
      address 1: 132.241.5.10
      address 2: 132.241.5.10
假如你需要保存这个IP地址,使用strcopy()函数来指向你自己的字符指针。
 
  转自 http://www.blog.edu.cn/user2/36539/archives/2006/1197635.shtml 
posted @ 2008-07-22 01:41 hihee的博客 阅读(52) | 评论 (0)编辑 收藏

2008年7月20日 #

getopt  详解

getopt()函数声明如下:
#include <unistd.h>

int getopt(int argc, char * const argv[], const char *optstring);

extern char *optarg;
extern int optind, opterr, optopt;
该函数的argc和argv参数通常直接从main()的参数直接传递而来。optstring是选项字母组成的字串。如果该字串里的任一字符后面有冒号,那么这个选项就要求有选项参数。
当给定getopt()命令参数的数量 (argc)、指向这些参数的数组 (argv) 和选项字串 (optstring) 后,getopt() 将返回第一个选项,并设置一些全局变量。使用相同的参数再次调用该函数时,它将返回下一个选项,并设置相应的全局变量。如果不再有可识别的选项,将返回 -1,此任务就完成了。

GNU提供的getopt()函数,它会扫描整个命令行来寻找选项。当调用GNU getopt()函数并处理命令行参数的时候,它重新排列argv中的元素,这样当重排结束时,所有选项都被移动到前面并且那些继续检查argv [optind]至argv[argc-1]中剩余参数的代码仍正常工作,但在任何情况下,碰到特殊参数'--'就结束对选项的扫描。


getopt() 所设置的全局变量包括:
? char *optarg——当前选项参数字串(如果有)。
? int optind——argv的当前索引值。当getopt()在while循环中使用时,循环结束后,剩下的字串视为操作数,在argv[optind]至argv[argc-1]中可以找到。
? int opterr——这个变量非零时,getopt()函数为“无效选项”和“缺少参数选项,并输出其错误信息。
? int optopt——当发现无效选项字符之时,getopt()函数或返回'?'字符,或返回':'字符,并且optopt包含了所发现的无效选项字符。

getopt()对错误命令行参数信息的输出行为

不正确的调用程序在所难免,这种错误要么是命令行选项无效,要么是缺少选项参数。
正常情况下,getopt()会为这两种情况输出自己的出错信息,并且返回'?'。

如果不希望输出任何错误信息,或更希望输出自定义的错误信息。
可以采用以下两种方法来更改getopt()函数的出错信息输出行为:
1. 在调用getopt()之前,将opterr设置为0,这样就可以在getopt()函数发现错误的时候强制它不输出任何消息。
2. 如果optstring参数的第一个字符是冒号,那么getopt()函数就会保持沉默,并根据错误情况返回不同字符,如下:
o “无效选项” —— getopt()返回'?',并且optopt包含了无效选项字符(这是正常的行为)。
o “缺少选项参数” —— getopt()返回':',如果optstring的第一个字符不是冒号,那么getopt()返回'?',这会使得这种情况不能与无效选项的情况区分开。

#include <stdio.h>
#include <unistd.h>

int main (int argc, char **argv)
{
    int oc;                     /*选项字符 */
    char ec;                    /*无效的选项字符*/
    char *b_opt_arg;            /*选项参数字串 */

    while((oc = getopt(argc, argv, ":ngl:")) != -1)
    {
        switch(oc)
        {
            case 'n':
                printf("My name is Lyong.\n");
                break;
             case 'g':
                printf("Her name is Xxiong.\n");
                break;
            case 'l':
                b_opt_arg = optarg;
                printf("Our love is %s\n", optarg);
                break;
            case '?':
                ec = (char)optopt;
                printf("无效的选项字符 \' %c \'!\n", ec);
                break;
            case ':':
                printf("缺少选项参数!\n");
                break;
        }
    }
    return 0;
}

 

posted @ 2008-07-20 02:30 hihee的博客 阅读(81) | 评论 (0)编辑 收藏

2008年7月19日 #

#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#define INPUT_FILE "/home/chen/temp/temp/input.txt"

int main()
{
        FILE *in;
        char buffer[1024];
        pid_t pid;
        int delete_num; // 欲删除的行数
        char fro_to[20];
        int status;
        unsigned long lines = 0;

        in = fopen(INPUT_FILE, "r");
        if (NULL == in)
        {
                printf("fopen error!\n");
        }

        while(NULL != fgets(buffer, sizeof(buffer), in))
        {
                lines++;
        }

        // 输出文件的总行数
        printf("The file \"%s\" has %ld lines.\n", INPUT_FILE, lines);
        if (0 == lines) return 0;

        printf("You want to delete fomr 1 to __:");
        scanf("%d", &delete_num);
        sprintf(fro_to, "1, %dd", delete_num);

        while (delete_num > 0 && delete_num <lines + 1 )
        {
                pid = fork();
                if (-1 == pid)
                {
                        perror("fork failed!\n");
                        return(1);
                }
                else if (0 == pid)
                {       /* pid为0,子进程 */
                        execlp("sed", "sed", "-i", fro_to, "input.txt",(char *)0);
                        perror("execl failed!\n");
                        _exit(2);
                }
                else
                {
                        /* pid大于0,父进程 */
                        break;

                }
        }
        wait(&status);
        printf("ok, successfull!\n");
        return(0);
}

 

posted @ 2008-07-19 01:51 hifreebsd@tom.com的博客 阅读(76) | 评论 (0)编辑 收藏

2008年7月10日 #

我总算是看懂了,  转自http://baike.baidu.com/view/469071.htm
 
base64 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,
大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。
Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),
然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。
这样说会不会太抽象了?不怕,我们来看一个例子:
转换前 aaaaaabb ccccdddd eeffffff  
转换后 00aaaaaa 00bbcccc 00ddddee 00ffffff
应该很清楚了吧?上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。
转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),
 
这个表是这样的:(摘自RFC2045)

                            Table 1: The Base64 Alphabet
      Value Encoding  Value Encoding  Value Encoding  Value Encoding
           0 A            17 R            34 i            51 z
           1 B            18 S             35 j            52 0
           2 C            19 T             36 k            53 1
           3 D            20 U            37 l            54 2
           4 E            21 V             38 m            55 3
           5 F            22 W            39 n           56 4
           6 G            23 X             40 o           57 5
           7 H            24 Y             41 p           58 6
           8 I             25 Z               42 q          59 7
           9 J             26 a               43 r           60 8
          10 K            27 b             44 s           61 9
          11 L            28 c              45 t            62 +
          12 M            29 d            46 u           63 /
          13 N            30 e             47 v
          14 O            31 f             48 w         (pad) =
          15 P            32 g             49 x
          16 Q            33 h             50 y

让我们再来看一个实际的例子,加深印象!
转换前 10101101    10111010    01110110  
转换后 00101011    00011011    00101001   00110110
十进制 43 27 41 54
对应码表中的值 r b p 2

所以上面的24位编码,编码后的Base64值为 rbp2
解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。
(解码只是编码的逆过程,在此我就不多说了,另外有关MIME的RFC还是有很多的,如果需要详细情况请自行查找。)
用更接近于编程的思维来说,编码的过程是这样的:
第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符。
然后将第一个字符左移4位加上第二个字符右移4位,即获得第二个目标字符。
再将第二个字符左移2位加上第三个字符右移6位,获得第三个目标字符。
最后取第三个字符的右6位即获得第四个目标字符。
在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。
可是等等……聪明的你可能会问到,原文的字节数量应该是3的倍数啊,如果这个条件不能满足的话,那该怎么办呢?
我们的解决办法是这样的:原文的字节不够的地方可以用全0来补足,转换时Base64编码用=号来代替。
这就是为什么有些Base64编码会以一个或两个等号结束的原因,但等号最多只有两个。因为:
余数 = 原文字节数 MOD 3
所以余数任何情况下都只可能是0,1,2这三个数中的一个。
如果余数是0的话,就表示原文字节数正好是3的倍数(最理想的情况啦)。
如果是1的话,为了让Base64编码是4的倍数,就要补2个等号;
同理,如果是2的话,就要补1个等号。
 
 
posted @ 2008-07-10 00:54 hifreebsd@tom.com的博客 阅读(49) | 评论 (0)编辑 收藏

2008年7月8日 #

看了还不错, 转贴 http://hi.baidu.com/jk_cau/blog/item/619858351ab4488ea61e129f.html 
查看文章  
char (*p)[10] 与 char p[10]
2008-06-17 16:10
1、char p[10]
p是数组类型。它指代数组。属于char [10]类型,(不是char *类型,和指针不要简单的混为一谈哦)。
2、char (*p)[10]
p是指向一个char [10]型数组的指针。因此,若有char q[10],则p是指向q的指针。因此,有p=&q。
注:p=q 报错。因为p是指向数组的指针类型(指向 char [10]类型的指针 ----char (*)[10]),而q是数组类型(char [10]),类型明显不符。因此用p=&q。(对比理解:int a=5;int *pa;pa=a;(error)pa=&a;(right))。
例子:
#include "stdafx.h"
#include "iostream"
using namespace std;

int main()
{
char (*p)[10];
char q[10]="hello,guy";
p=&q;
cout<<sizeof(p)<<" "<<sizeof(q)<<endl;    
cout<<q<<endl;
cout<<p<<endl;
cout<<*p<<endl;
cout<<*q<<endl;
cout<<**p<<endl;
return 0;
}
***********************************************
4 10                      //sizeof(q):sizeof(char)*10
hello,guy               //q指代的是整个数组,因为q是数组类型,不是指针类型
0012FF70             //p指向数组,p中的数据是数组的首地址。
hello,guy               //*p即是q(p=&q)
h                           //*q,似乎比较特殊(有点说不清了,呵呵),是数组第一个元素。
h                           //**p即是*q。
Press any key to continue
posted @ 2008-07-08 13:31 hifreebsd@tom.com的博客 阅读(58) | 评论 (0)编辑 收藏

我已毕业了, 28号离开了焦作,
真不知道什么时候能再回去呀.
宿舍几个各奔南北去了;
李建,振豪,国元,罗军,阿基,长久,我,
----来自406的一群小伙子, 还有戴正旺,小娟,
还有薛艳,安晋超,石作敏
各奔南北了.
 
 
 
posted @ 2008-07-08 13:27 hihee的博客 阅读(51) | 评论 (0)编辑 收藏

2008年6月9日 #

平常写一写,就当作练习吧。
 
typedef int ElemType;
typedef struct
{
    ElemType elem[MAXSIZE];
    int top;
}SeqStack;
// 栈初始化
void Init_SeqStack(SeqStack *s)
{
    s->top = -1; 
}
// 判断栈是否空
int Empty_SeqStack(SeqStack)
{
    if (s->top == -1) return true;
    else
     {
         return true;
      }
}
// 入栈
int Push_SeqStack(SeqStack *s)
{
    if (s->top == MAXSIZE -1) return OVERFLOW; // 上溢
    else
    {
        s->top++;                    // 栈顶指针加1
        s->elem[s->top] = x;    // 存入栈顶值
        return OK; 
    }
}
// 出栈
int Pop_SeqStack(SeqStack *s, ElemType *y)
{
    if (Empty_SeqStack(s)) return OVERFLOW; // 空栈
    else
    {
        *y = s->elem[s->top];   // 取得栈顶值
        s->top--;                       // 栈顶指针减1
        return OK; 
    }
}
// 取栈顶元素
ElemType Top_SeqStack(SeqStack *s)
{
    if (Empty_SeqStack(s)) return OVERFLOW; // 空栈
    else
    {
        return (s->elem[s->top]);
    }
}
posted @ 2008-06-09 01:20 hifreebsd@tom.com的博客 阅读(111) | 评论 (0)编辑 收藏

2008年6月1日 #

今天,把DOS装进126m人U盘了,其实我把U盘格式成fat(不是fat32呀),
选的是USB-ZIP模式,真不错,也不怕没光驱了,然后我把MaxDOS也拷进去,
也可以用maxdos。
 
我还把1G的U盘,装了个slax linux,还不错,才200M不到,里面挺全的,
不过救急就够了,以后慢慢玩玩,不过没有MAKE,GCC,看来有空给装上去。
posted @ 2008-06-01 00:21 hifreebsd@tom.com的博客 阅读(234) | 评论 (0)编辑 收藏

2008年5月25日 #

用django写了个简易的在线聊天,用的是sqlite数据库,
以前看过php, 知道如何写在线聊天。
其实就是frameset那边设置一下,自己把它认为一下子打开了几个网页,
但是同时打开时,在浏览器的地址栏上我们只能看到其中一个,
另外几个子frame 的地址把其认为是在后台打开,同时也得到urls.py中设置一下,
frame中的src设置成相对的路径就行了。
 
因为学校的网络真的不好,经常几天上不了网,
因此这次想到了用网页进行在线聊天,非常简单的聊天,只能传送文字。
不过我也不打算继续深入做这个在线聊天,一时间不够,二来精力有限呀。
但愿以后有空,抽出时间继续做下去。
唉,如果早两年写出来就好了。
 
posted @ 2008-05-25 02:27 djalion(亮)的博客 阅读(246) | 评论 (1)编辑 收藏