FightingMan's FootPrints

I know the only way to success for me is do it forever and never give up.

Big and Little Endian in Inet_pton()

| Comments

今天弄懂了昨天那篇文章Socket编程遇到字节排序的诡异问题里的疑惑:

main.c
1
2
3
4
5
6
7
8
9
10
#include <stdlib.h>
#include <stdio.h>
#include <arpa/inet.h>

int main() {
    struct in_addr addr;
    inet_pton(AF_INET, "127.0.0.1", &addr);
    printf("%x\n", addr.s_addr);
    return 0;
}
输出:100007f

开始就觉得很不解,127.0.0.1转为网码不是应该7f000001吗,为什么这里会这么奇怪而且头文件里面定义的

# define INADDR_LOOPBACK    ((unsigned long int) 0x7f000001)

也确实是7f000001,后来再次翻了inet_pton()函数的源码

inet_pton.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
int
inet_pton(af, src, dst)
  int af;
  const char *src;
  void *dst;
{
  switch (af) {
  case AF_INET:
      return (inet_pton4(src, dst));
  case AF_INET6:
      return (inet_pton6(src, dst));
  default:
      __set_errno (EAFNOSUPPORT);
      return (-1);
  }
  /* NOTREACHED */
}
libc_hidden_def (inet_pton)

static int
internal_function
inet_pton4(src, dst)
  const char *src;
  u_char *dst;
{
  int saw_digit, octets, ch;
  u_char tmp[NS_INADDRSZ], *tp;

  saw_digit = 0;
  octets = 0;
  *(tp = tmp) = 0;
  while ((ch = *src++) != '\0') {

      if (ch >= '0' && ch <= '9') {
          u_int new = *tp * 10 + (ch - '0');

          if (saw_digit && *tp == 0)
              return (0);
          if (new > 255)
              return (0);
          *tp = new;
          if (! saw_digit) {
              if (++octets > 4)
                  return (0);
              saw_digit = 1;
          }
      } else if (ch == '.' && saw_digit) {
          if (octets == 4)
              return (0);
          *++tp = 0;
          saw_digit = 0;
      } else
          return (0);
  }
  if (octets < 4)
      return (0);
  memcpy(dst, tmp, NS_INADDRSZ);
  return (1);
}

Socket编程遇到字节排序的诡异问题

| Comments

通常大家这样绑定某个地址

server.cpp
1
2
3
    ...
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    ...

如果网卡多,只想在某一网卡的某个地址上bind怎么办呢?就需要指定s_addr的地址 比如:192.168.1.102

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    //main.cpp
    include <iostream>
    #include "server.h"
    using namespace std;

    int main(int argc, char* argv[]) {
        try {
            if (argc != 4)  {
                cerr << "Usage: ftsrv <address> <port> <doc_root>\n";
                return 1;
            }
            ftsrv::server s(argv[1], argv[2], argv[3]);
            s.run();
        } catch(exception& e) {
            cerr <<
                "exception:" <<e.what()<< "\n";
        }

        return0;
    }
    //server.h
    ...
    explicit server(const string& address_, const string& port_, const string& doc_root_);
    ...

Short Notes

| Comments

好记性不如烂笔头,很久没写博客了,重新开始吧。 我这种半路出家的酱油程序员,最近看算法学习了很多东西,很多东西有耳目一醒的感觉。 今天看到一道题,对位的操作算是,第一次比较熟悉的用了下:

如何判断n的第i位是否为1:n & (1 << i).

顺便想了下之前对位操作的总结:

按位与通常用来将变量中的某些位清0同时保留某些位不变: n &= 0xffffff00,低八位全为0.
按位或通常用来将变量中得某些位设置为1同时保留某些位不变:n |= 0xff,低八位全为1.
按位异或有个特点:a ^ b === c => c ^ b == a & c ^ a == b.可以快速简单的加解密.
左移n位就等于乘以2的n次方.
右移n位就等于除以2的n次方,并且将结果往小里取.

A Trap in Php Base_convert

| Comments

Today I find an interesting thing: a php function base_convert

convert.php
1
2
$a = 0x80;
var_dump(base_convert($a, 16, 2));

No surprises:

string(9) "100101000"

Let’s go on!

convert.php
1
2
3
4
$a = 0x80;
var_dump(base_convert($a, 16, 2));
$b = ~$a;
var_dump(base_convert($b, 16, 2), $b);

output:

string(9) "100101000"
string(9) "100101001"
int(-129)

Hmm,it seems strange that binary 100101001 not equas decimal -129, but the result: -129 is the right answer,what happened?

Shell Tips With Ctrl+(?)

| Comments

There are some handy operator with command line:

[Ctrl-d] #This exits shell or closes input on programs waiting for STDIN.NOTE: there must be no such thing as an end of file character.
[Ctrl-z] #This suspend a process u r running in foreground. Get it back by running 'fg', background it using 'bg'.
[Ctrl-c] #This canceling a running program,Ctrl-C can be used before you run cammand to "cancel" the line edit and start anew.
[Ctrl-b] #Move to the begging of the current or previous word. NOTE: base on keyboard mapping sometimes.
[Ctrl-f] #Move to the end of the current or next word. NOTE: base on keyboard mapping sometimes.
[Ctrl-w] #Remove the previous word.
[Ctrl-l] #Clear screen.
[Ctrl-K] #Delete/Yank everything from cursor to the end of line.
[Ctrl-U] #Delete/Yank everything from cursor to the begging of the line.
[Ctrl-e] #Move your cursor to the end of the line.
[Ctrl-a] #move your cursor to the begging of the line.
[Ctrl-r] #Reverse search through your command history for 'input'. ESC when done.
[Ctrl--] #Manial lists this as Ctrl-_ but Ctrl-- ususally works too.Incremental undo of command line edits.

Look forward to your supplementary :).