Skip to main content

· 3 min read

pack & unpack

根據特定的格式來讀取或封裝資料。

格式部份分成兩個部份

byte-order: 這邊可以決定採用big-endian 或是 little endian, 如果沒有給的話,預設是採用系統的方式去做,那這邊比較要注意到的是 以前再寫C語言的時候,都會有所謂的htons...類的轉換,在這邊可以使用'!' 這個符號來解決這個問題,他會自己使用network的Byte order rule去解讀資料,所以有在用網路連線傳資料的話,一定要用! 避免資料解讀錯誤的問題。

format-characters:

常用的有

  • x:pad byte,就忽略他
  • h:short,2 Byte
  • s:char[], 代表字串,使用時前面要加上數字
  • i:long int, 4Byte
  • B:unsigned char, 1 Byte

詳細的格式資訊請參考官網 Python struct

這邊來個簡單範例 假設今天我們撰寫屬於自己的網路遊戲 然後我們玩家每次上線時,SERVER都會傳送一份玩家的資料給Client

這份資料包含了

  • 遊戲版本
  • 玩家ID
  • 玩家的座標(XY)
  • 玩家當前的財產
  • 玩家的職業
  • 玩家的等級
  • 玩家的經驗值

每個資料所需要的型態跟大小如下敘述

Myheader(){
uint8:version
uint8:playerID
uint16:x
uint16:y
uint32:momey
char10:profession
uint8:level
uint32:experience
}

所以傳送資料過來的時候,我們必須要謹慎的按照這個規格去放置我們的資料。

Example

假設

  • version = 1
  • playerID = 56
  • x = 123
  • y = 2341
  • momey = 5566217
  • profession = "warrior"
  • level = 128
  • experience = 2147383611
data = pack('2B2HI10sBI',version,playerID,x,y,momey,profession,level,experience)
//'\x018{\x00%\t\x00\x00\t\xefT\x00warrior\x00\x00\x00\x80\x00\xdb\xff\xff\x7f'
unpack('2B2HI10sBI',data)
(1, 56, 123, 2341, 5566217, 'warrior\x00\x00\x00', 128, 2147483611)

· 2 min read

nmap是一個linux下的工具

nmap - Network exploration tool and security / port scanner

這邊記錄一下nmap的用法

nmap -sP 140.113.214.79/27

-sP: Ping Scan - go no further than determining if host is online 用ping去掃目標內的所有IP,並顯示有回應的IP,所以若對方是windows7且沒有打開ping的回應,則也會被當作host down

nmap -sL 140.113.214.79/27

-sL: List Scan - simply list targets to scan 只是單純的列出對方的hostname以及IP,不送出任何封包去檢測

nmap -O 140.113.214.94 nmap -A 140.113.214.94

-O: Enable OS detection -A: Enables OS detection and Version detection, Script scanning and Traceroute

掃描對方主機的OS系統

nmap -PS/PA/PU/PY[portlist] 140.113.214.94

-PS/PA/PU/PY[portlist]: TCP SYN/ACK, UDP or SCTP discovery to given ports

用不同的方式去掃描特定的PORT。

  • PS 用TCP 搭配 SYN FLAG去偵測。
  • PA 用TCP 搭配 ACK FLAG去偵測。
  • PU 用UDP去偵測。
  • PY 用SCTP去偵測。

nmap -sS/sT/sU 140.113.214.94

採用不同的方式去掃描所有port。

  • sS (TCP SYN scan) .
  • sT (TCP connect scan)
  • sU (UDP)

nmap -v 140.113.214.94 顯示出詳細一點的資訊

· 3 min read

Python中有個很強大的字串轉換工具 maketrans 跟 translate

str.translate(table[, deletechars]);
Parameters
table -- You can use the maketrans() helper function in the string module to create a translation table.

deletechars -- The list of characters to be removed from the source string.

字串中只要有符合deletechars中的字元都會被刪除,然後剩下的字元就會依照table裡面的mapping來做轉換。

這個mapping的就要利用string.maketrans()來幫忙產生囉,

str.maketrans(intab, outtab]);
Parameters
intab -- This is the string having actual characters.

outtab -- This is the string having corresponding mapping character.

intab跟outtab兩者的長度必須要一樣,會把intab中每一個字元與outtab中相同位置的字元做mapping。

舉例來說

    intab = "aeiou"
outtab = "12345"
trantab = maketrans(intab, outtab)

就會產生一個mapping,把aeiou分別轉換成12345。

    input="abcdefgh"
input = input.translate(trantab)

input就會變成 "1bcd2fgh"

那如果改成

    input="abcdefgh"
input = input.translate(trantab,"fgh")

input就會變成 "1bcd2"

再來個簡單範例,希望能夠把所有的小寫轉成大寫,並把非英文字母外的所有字元都給刪除掉。

import string

#取得所有英文大小寫的集合

    lower = ''.join(map(chr,range(97,123)))
upper = lower.upper()

#創立一個對照表,可以把所有小寫轉成大寫

    ltu = string.maketrans(lower,upper)

#接下來要利用捕集的方式取得非英文字母以外的所有字元,因此就用所有字元-英文字母 #創立一個代表所有字元的字元表

    allchars = string.maketrans('','')

#利用translate的方式,取得所有非英文字母的集合

    delete = allchars.translate(allchars,lower+upper)

#定義一個對應的function,傳入的字串利用ltu跟delete,就能夠把所有非英文字母都刪除,並且小寫轉大寫了。

    def makefilter(input):
print input.translate(ltu,delete)

· 3 min read

Msn的log採用的格式是XML,隨便打開一個LOG後仔細檢視,可以發現msn log的訊息格式大概是採這樣

    <Message Date="2012/3/23" Time="下午 11:33:12" DateTime="2012-03-23T15:33:12.790Z" SessionID="1">
<From><User FriendlyName="邱 渣"/></From>
<To><User FriendlyName="XXX"/></To>
<Text>明天會到否</Text>
</Message>

每一則訊息,本身的屬性會包含該訊息的發送時間 ,有兩種格式,後面的790Z就不清楚是什麼意思了,SessionID這個屬性

也不是很清楚,但是這些都不重要

利用Date跟Time就可以取得基本時間了。

接者可以看到底下有三個屬性,代表訊息發送者,訊息接收者,以及發送的訊息為何

如果有啟動顏色跟字型的話,TEXT欄位就會變成下列樣子,會有屬性標示其顏色與字型

    <Text Style="font-family:Microsoft JhengHei; color:#000000; "> test </Text>

在C#中,我這次使用XmlElement來做為解析XML的工具,載入檔案後,因為我們只關心訊息的傳送,

所以先利用GetElementsByTagName("message")來取得所有Message有關的nodes

接者針對這個結點內的所有資料去進行資料抓取,我們的目標有 時間、發送者、傳送文字

先將XmlNode轉型為XmlElement的類型,這樣方便處理,然後利用GetAttribute來取得Message的屬性

我們就可以知道每個對話的Date跟Time。接者要存取其child(From,To,Text)這些的值

這邊比較要注意的是這兩種的差別

    <From>"邱渣"</From>
<From><User FriendlyName="邱渣"/></From>

以Type1來說,邱渣是From這個結點的值,可以利用childList[0].value 取得發送者的名稱

但是對Type2來說,邱渣是From這個結點底下的一個結點中的屬性,所以就要利用childList[0].FirstChild

的方式來取得<User>這個結點,再搭配Attributes[0].Value來取得第一個屬性的值,如此才可以取得"邱渣"的值

所以利用childList[2].FirstChild.Attributeds[0].Value就可以取得文字訊息了!

另外,如果要取得文字的顏色跟字型的話,利用

childList[2].GetAttribute("Style")

接者在去自己處理字串來取得字型跟顏色。

範例code如下

    xml = new XmlDocument();
xml.Load(filename);
XmlNodeList nodeList = xml.GetElementsByTagName("Message");
foreach (XmlNode parentNode in nodeList)
{

XmlElement element = (XmlElement)parentNode;
string Date = element.GetAttribute("Date");
string Time = element.GetAttribute("Time");
XmlNodeList childList = element.ChildNodes;
data += childList[0].FirstChild.Attributes[0].Value + " 說 (" + Time + ")\r\n";
}

· 4 min read

#[User]

不論是bash,tcsh,又或者是windows的cmd,都有一種叫做PIPE的功能

能夠將兩個獨立的程式給串接起來,把前面程式的輸出當作下一個程式的輸入

擁有這個指令,就能將本來當一功能的程式給組合起來變成複雜的工具了

舉例來說,我想要知道我當前目錄下有多少個檔案

就可以使用ls跟wc兩個指令合作完成,

使用 ls | wc 就會將ls的結果(檔案列表)當作輸入傳給wc這隻程式,然後就可以輕鬆地算出當前目錄的檔案數量

或者是有時候想要搜尋某些特定的字串,都會使用grep這個指令,譬如想要搜尋某個特定使用者正在執行的所有程序

ps auxww | grep username

所以pipe對於系統管理來說,是個非常重要的概念,能夠將每個獨立細小的程式給串接起來完成複雜的工作。

#[程式設計]

在FreeBSD(linux)上,shell能夠辦得到這樣的功能,實際上是利用了kernel中pipe的功能,這邊就已linux kernel 3.5.4為架構。

在程式中,pipe的概念就是一個水管,這個水管有兩個端口,一端負責寫資料到pipe,一端負責將資料從pipe中讀出來,所以我們可以做個簡單的測試。

int main(){
int rand1,rand2;
int fd[2];// declare a two-d array, store file_descriptor of the pipe (two side)
// fd[0] mease read side, fd[1] means write side
pid_t pid;//child process的pid
pipe(fd); //call system call (pipe) to create a pipe
//use fork to create a child process
//child process will wrtie data to pipe, and parent will read data from pipe
//child process
if((pid=fork())==0){
srand(getpid());
close(fd[READ_END]);//child won't use read size, so close it
rand1=rand()%RANGE; //create random number
write(fd[WRITE_END],&rand1,sizeof(rand1)); //write to pipe
close(fd[WRITE_END]);//close write side when write over
printf("%d has been created In Child Process \n",rand1);
exit(1);
}
else if(pid>0){
srand(getpid());
close(fd[WRITE_END]);//parent won't use write size, so close it。
rand2=rand()%RANGE;//create random number
read(fd[READ_END],&rand1,sizeof(rand1));//read the data from pipe
printf("%d has been created In Parent Process \n",rand2);
wait();
printf("Parent Process calulate sum is :%d \n",rand1+rand2);
close(fd[READ_END]);//close read side
exit(1);
}
return 0;
}

執行結果: 8 has been created In Child Process

5 has been created In Parent Process

Parent Process calulate sum is :13


3 has been created In Child Process

3 has been created In Parent Process

Parent Process calulate sum is :6

實際上,如果想要對同個端口去進行寫跟讀的動作,是行不通的,乍看之下會覺得PIPE只是一個

buffer,放置資料而已,實際上在kernel中,pipe被視為是一個file,當我們呼叫pipe時,真正最後會

呼叫到do_pipe這個function,在這個function中,會針對pipe的兩個端口分別去設定

O_RDONLY;O_WRONLY的標籤,這樣的設定使得pipe的端口就真的一邊只能讀,一邊只能寫。

有空在來講述一下file_descriptor file file_operation三者的關係,以及到底 file,socket,pipe...等這些device到底在kernel中如何運作。

· 3 min read

應朋友的要求,用matlab幫忙寫了一個簡單的腳本

需要能夠ˋ彈出對話框選擇一個資料夾,讀取資料夾底下的影像檔,然後與某個特定的影像檔做相減,並命名輸出

這部分用到了一些指令,在這邊紀錄下來

%choose directory
target_path = uigetdir();
file_path = [target_path '/C00*.tif'];
background = [target_path '/REF.tif'];
file_struct = dir(file_path);
back_struct = dir(background);

%load background image
back = imread([target_path '/' back_struct.name]);
for i=1:length(file_struct)
temp_image = imread([target_path '/' file_struct(i).name]);
result_image = imsubtract(temp_image,back);
imwrite(result_image,[target_path '/new' file_struct(i).name]);
end

====END=======

首先使用到了uigetdir,與其類似的還有uigetfile

呼叫此函數後,會彈出directoryOpenDialog的介面,選擇完畢後,會把選擇的路徑回傳

接下來我想要移動到該路徑,於是希望透過 cd 這個指令,無奈 cd這個指令沒有辦法吃參數,只能吃完整路徑,所以就必須要改換成其他的方法

由於我已經知道圖檔的命名規則,於是先用 [] 的方式,把字串給連接起來,這邊使用regular的方式,之後再搜尋檔案的時候會更方便

接者使用dir這個指令,就可以得到我想要的所有檔案,dir回傳的是一個struct,內容包含了檔案的

name -- 檔案名稱 date -- 修改日期 bytes -- 檔案大小 isdir -- 是否為資料夾 datenum -- Matlab特定的修改日期

這邊我只需要它的名稱,於是透過一個迴圈,把所有的路徑檔案都以圖片的方式(imread)給讀取近來 在與事先讀取好的背景圖片(back)使用imsubtract做相減,得到新的圖片,再透過imwrite給寫出檔案

· 2 min read

最近因為某個教授的要求,希望windows開機就可以自動vpn連線,所以這部份花了一些時間去研究,雖然我認為每次開機自己動手點兩下好像也沒有多困難阿~冏

這個概念其實不難,寫一個可以連線的batch file,每次開機的時候,自動去執行該batch file,就可以達到連線的功能了。

  1. 在網際網路那邊手動增加一個VPN連線,假設該VPN連線名稱為 vpn_connection。

  2. 寫一個batch file,內容增加一行

rasdial "my_vpn_connection" "myname" "mypasswd"

這時候可以手動執行看看,看會不會連線成功,如果連線不會成功,就根據錯誤代碼去解決。

  1. 執行taskschd.msc 這個排班程式,把該batch file加入至開機執行,並且在網路連線成功後才執行。

重開機測試!

· One min read

C++中,有所謂的顯性轉換跟隱性轉換

在宣告時,加入explicit 這個關鍵字,可以禁止使用顯性轉換,以下為例

    using namespace std;
class Stack {
public:
Stack(int a){};
};
void Test(Stack b){
}
int main()
{
Stack s1 = 1; //ok
Stack s2 = Stack(12); //ok
Stack s3(s1); //ok
Test(123); //ok
return 0;
}
    using namespace std;
class Stack {
public:
explicit Stack(int){};
};
void Test(Stack b){
}
int main()
{
Stack s1 = 123; //error
Stack s2 = Stack(123); //ok
Stack s3(s1); //ok
Test(123); // error
return 0;
}
Tags:

· 2 min read

有時候根據應用需求,會需要針對去檢查目前系統上有哪些port正在被使用

#[FreeBSD]

可以使用 sockstat 這個command 來檢查系統上port的使用。

USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS

root cron 93468 4 udp4 :638 :*

在預設的情況下,會輸出

使用者名稱,執行的程序,該程序的pid,在該程序中使用該port的file descriptor是多少 使用何種協定,以及address

如果使用 sockstat -4lP tcp 就可以找出 使用tcp & ipv4 ,並且正在listen的port

這對於要尋找是否有人在寫Socket programming來說是很方便的。

詳細的可以man sockstat


#[Linux] 可以使用 netstat 這個工具來檢視,搭配一些參數還可以看到該 port 被那些 process 使用

netstat -anptn
tcp 1 0 127.0.0.1:40147 127.0.0.1:36524 CLOSE_WAIT 7147/vim
tcp 1 0 127.0.0.1:58289 127.0.0.1:52849 CLOSE_WAIT 19421/vi
...

#[Windows]

可以使用netstat來檢視,netstat能夠顯示的資訊非常的多,為了精簡我們的需求,必須去過濾這些資訊

在windows上使用find這個指令,類似於UNIX中grep的功能

舉例來說,netstat -an |find /i “listening" 這個指令

netstat -an 會顯示所有連線以及正在監聽的port,並且以數字的形式來顯示IP以及PORT

find /i “listening" 則會以不區分的方式去搜尋每一行,若包含listening則將該行印出

EX:

TCP 192.168.1.116:139 0.0.0.0:0 LISTENING

TCP 192.168.1.116:49156 216.52.233.65:12975 ESTABLISHED

ref: www.microsoft.com/resources/