新年第一篇網誌,竟然是 Linux學習筆記..."orz
這篇也是補兩個禮拜前的課程
由於學校因為聖誕節跟元旦放掉兩個星期四的關係
這篇也是Linux程式設計的最後一堂課的內容
接下來只要考完下禮拜的期末考,本學期就正式結束了︿( ̄︶ ̄)︿

===
ch 15 Sockets
===
沒有socket就沒辦法上網,沒辦法上網就...不好玩了XD
C的socket寫法較複雜,JAVA、.NET都把它包起來了,更好用

‧socket是pipe的延伸
pipe是建立一個通道,藉由通道傳遞我的訊息
任何人只要知道我的pipe檔名,就可以跟其他人做溝通
缺點是pipe只能在本機電腦上

socket是一個機制,允許client跟server溝通
socket跟pipe一樣可以read跟write
而且它還能夠跨越網路
所以process要跟process做溝通,不一定要在同一台電腦上

Windows跟Linux都可以利用Socket跟對方作溝通
我們不用知道對方是什麼系統就可以做溝通
這都是socket的功勞
Windows的Socket規格稱為WinSock

socket連線步驟
1. 通常server的應用程式需要先產生socket,使用system call socket
2. 然後要給socket一個名字(port 80)
(port理論上只有65000多個)
3. socket取名稱做systen call bind
4. server會等待client連線
5. system call listen,並產生一個queue讓client連線
6. 系統可以system call accept來允許連線

更詳細的訊息,請參考man socket

15-01.gif

‧關鍵字前面為AF_代表為address family
PF_為protocol family

PF_UNIX跟PF_LOCAL不是跨越網路,而是在檔案系統溝通
PF_INET使用IPv4的網路協定
PF_INET6當然就是使用IPv6的協定了

請參考
man 7 unix - 看socket的詳細結構
man 7 ip - ipv4的通訊協定

‧client1 & server1
跟上次pipe類似,但稍有不同
如果先執行./client1會顯示找不到檔案
要先執行./server1
此時可以輸入ll *sock*來看一下socket的存在
發現有產生後,再執行./client1才會看到正確的結果

順便一提,結束掉server1後,socket還是存在喔
請用rm *sock*清空

15-03.gif
15-02.gif

‧socket的語法
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

AF_UNIX  - 只在本機內連線
SOCK_STREAM  - 類似TCP的串流
0  - Protocol,一般都給0

‧connect的語法
result = connect(sockfd, (struct sockaddr *)&address, len)
sockfd  - 剛剛的socket
(struct sockaddr *)&address  - 結構
len  - address長度

注意struct sockaddr_un要轉成struct sockaddr *

unlink - 把字串所指的目錄unlink掉
請參考man 2 unlink

15-04.gif

server是用一個迴圈一直讀值
如果給server不同的socket名字,client就讀不到了

把server1給Ctrl+C強制中斷
socket檔案還是會在
可是client去讀就會顯示Connection refused

15-05.gif

用以前的語法一樣連執行十次client1
因為我們執行太快了,所以不會有問題
for i in 1 2 3 4 5 6 7 8 9
do
./client1
done


cat /etc/services
這是所有port的用途列表
以前考過寫出五個已知的port
不過現在考試都用open book
查一下就有了,應該不會再考這個吧...

15-06.gif

Stream Socket類似TCP,保證會收到
Datagram Socket類似UDP,不一定會收到,順序不一定相同

‧accept connection如果不要停住就要加上O_NONBLOCK

‧client2 & server2
用網路方式傳送
注意看目錄底下是沒有socket的

15-07.gif

netstat -puta - 看有什麼socket

第二版的問題非常大!
port明明是設定9734(address.sin_port = 9734;
但內容卻是1574

15-08.gif

老師說是因為Network Byte Order的關係
要使用以下幾種函式把他們轉成長整數
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

像剛剛的程式就要改成address.sin_port = htons(9734);

‧client3 & server3
這樣就正常了

15-09.gif

‧getname
gethostbyname語法的範例
./getname
www.google.com.tw - google有三台伺服器服務台灣
./getname www.google.com.cn - 只有一台服務大陸

所以Google比較重視台灣(爆)

15-10.gif

‧getdate
從伺服器取得時間的範例(跟作業相關)
很糟糕的是,這個範例似乎只能連到區域網路(課本範例是連localhost)
如果我在家連線的話,就會告訴我"沒有權限"
連到其他地方則是回傳空字串(0 byte)

./getdate 163.14.68.15
./getdate ntp.scu.edu.tw - 學校的時間(登入學校才可用)
./getdate clock.hinet.net
- Hinet的時間

‧getdate-udp
用UDP方式取得時間
./getdate-udp ntp.scu.edu.tw
./getdate-udp clock.stdtime.gov.tw - 國家標準局的時間

作業三用TCP或UDP抓時間都可以
收到封包後就想辦法顯示時間(可是連範例都收不到怎麼辦?)
顯示時間的語法可用gettimeofday(&starttv, NULL);

下一次見面就是期末考,有一題會跟作業很像

arrow
arrow
    全站熱搜

    蕭雲 發表在 痞客邦 留言(2) 人氣()