日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

浅谈Socket编程

發布時間:2025/6/17 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈Socket编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

淺談Socket編程

說到Socket,想必大家會覺得陌生又熟悉。許多同學聽說過Socket,但僅僅知道它翻譯成中文叫做套接字,除此之外似乎并沒有太多的了解了。那么今天我就來拋磚引玉地聊一聊Socket。有人說

The lower application layers are all about socket programming
應用的底層全是和socket打交道

一看到涉及底層,有的同學就表示:
其實這些東西并不深奧,只要花一些時間去看,肯定是能夠看懂的,并且一但找到了點兒感覺,會覺得Socket非常有趣。
你難道不好奇瀏覽器是怎樣和web服務器勾搭在一起來取悅你的嗎?許多網絡應用都通過Socket來交流,所以Socket在網絡編程里占有了很重要的地位。
那么言歸正傳,到底什么是Socket的呢?——大學教材上的答案是套接字。我個人覺得這是一個不太好的翻譯,雖然說仔細一想有那么點兒意思,但是99%的人即使看見套接字這個詞,依然不知道是什么鬼,所以沒有翻譯的必要。就像Rap你硬要說中文翻譯叫拉普也沒啥意義對吧。
在Unix中,有一種說法叫

Everything is a file
一切皆文件

所以你只需要記住Socket是某種類型文件的抽象
怎么理解這句話呢?想象一下,假設你要開發一個網絡應用,需要在兩個客戶端之間發消息。整個過程可能包含以下步驟:

  • 客戶端組裝數據
  • 客戶端之間約定好數據格式
  • 客戶端向指定地址發送請求
  • DNS服務器解析請求地址
  • DNS沒有找到地址,然后跳轉到另一個DNS,一直到找到為止
  • 返回客戶端真實的IP
  • 客戶端向對應IP建立連接請求(三次握手)
  • 開始發送數據,窗口以2的k次冪大小滑動
    ……
    以上省略一本頁數為1047的《TCP/IP》
    有人可能已經噴了,你不是說Socket編程很簡單嗎,這還叫簡單?
    正因為這很復雜,所以前人們對這個過程進行了一種抽象,來幫助我們編程。
    你不就是想把數據發給對方嗎?組裝數據然后發給某人這個過程,和組裝好數據然后寫到某個文件里有什么區別呢?對了,沒有區別。
    Socket就是一種特殊的文件。它是一個連接了兩個用戶的文件,任何一個用戶向Socket里寫數據,另一個用戶都能看得到,不管這兩個用戶分布在世界上相距多么遙遠的角落,感覺就像坐在一起傳紙條一樣。
    這么講Socket應該更容易理解吧?這種抽象是非常重要的,因為它屏蔽了更底層的東西,我就想寫個程序發送下數據,為什么要關系物理層怎么傳輸呢,對吧。
    所以有了Socket的概念之后,我們在兩個客戶端之間發送消息可能就是這樣的:
  • 指定對方的地址
  • 打開一個和對方連接的Socket
  • 把Socket當成普通的文件,往里寫數據
  • 要是發現Socket里有數據,就讀出來,那必然是對方發過來的

這樣的話,網絡編程是不是就非常簡單了呢?
那么下面我們用Go語言作為示例,演示一下。

package mainimport ( "fmt" "net" "os" ) func main() { //使用tcp協議,要監聽的是6666端口 tcpAddr, err := net.ResolveTcpAddr("tcp", "localhost:6666") checkError(err) //開始監聽 fd, err := net.ListenTcp("tcp", tcpAddr) checkError(err) for { //獲取Socket conn, err := fd.Accept() if err != nil { continue } //你的邏輯 go Handle(conn) } } func Handle(conn *net.Conn) { //You can do anything you want to here... } func checkError(err error) { if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } }

端口是什么概念?可以近似這么想:一臺電腦就是你家的小區,你買東西如果填的地址是你家小區,那么快遞員最多能把東西送到小區門口;但是如果你寫上了你家的門牌號,那么快遞員就能送到你家門口。同樣的,電腦上同時運行著很多程序,比如QQ,旺旺…但是電腦只有只有一個IP地址,一條消息來了沒人知道這個消息是給誰的,于是就有了端口的概念。QQ在這臺電腦的4567端口,旺旺在這臺電腦1234端口。發消息的人只要知道它在什么端口,就能準確地把消息發過來了。
同樣的,網絡通信兩端的人得事先約定好一個端口,然后一個人守著這個端口,待另一方連接了這個端口,這才算建立了Socket連接。就好兩個人打電話,不需要關心信號怎么轉換和傳輸,但在建立這次通話之前必須有人撥號,同時有人守在電話旁。
于是上面的代碼應該就可以理解了吧?
一個程序猿走到"localhost:6666"這個“電話”旁邊

tcpAddr,err := net.ResolveTcpAddr("tcp","localhost:6666")`

然后坐下來等電話響

fd,err := net.ListenTcp("tcp", tcpAddr)

他也不知道女朋友什么時候打電話過來,于是開始了漫長的等待

//一個死循環 for { conn,err := fd.Accept() //電話沒有響就一直堵在上面這條語句 }

在漫長地等待中,突然電話響了,然后開始了一段佳話(程序終于不堵了,接著向下執行)

go Handle(conn)

Handle方法就用來處理對話,數據都在conn里面,只需要學習相關的API就能知道怎么把具體的內容取出來了。
整個過程是不是很簡單?
有些機智的同學可能已經發現了,要這樣的話,兩個人都在等對方打電話過來,豈不是就終身無緣了(這種誤會就像韓劇)。對的,所以我們還需要知道,如何給對方撥號。這是很關鍵的一步,一般妹子不好意思,那么自然我們得上了。
怎么撥號呢?請看代碼:

import ("fmt" "io/ioutil" "net" "os" ) func main() { tcpAddr, err := net.ResolveTcpAddr("tcp", "localhost:6666") checkError(err) conn, err := net.DialTcp("tcp", nil, tcpAddr) checkError(err) _, err = conn.Write([]byte("妹子,約嗎?")) result, err := ioutil.ReadAll(conn) //不約,叔叔我們不約 } func checkError(err error) { if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } }

解釋一下,一般妹子都比較含蓄,告訴你聯系方式不那么直接,你得破解一下

tcpAddr := net.ResolveTcpAddr("tcp", "localhost:6666")

呵呵,嘴上說不要身體卻很誠實嘛,這么容易就破解了。(其實是Go的包比較好用好嗎!)
然后按著電話號撥打電話

conn, err := net.DialTcp("tcp", nil, tcpAddr)

電話打通了,conn就代表這次通話。屌絲們已經急不可耐了,于是大喊一句:

_, err = conn.Write([]byte("妹子,約嗎?"))

為什么我第一個返回值用_,這表示我不想知道函數的返回結果,即Write了多少個字節。我問妹子約不約,你說我關不關心這句話包含幾個字節?

result, err := ioutil.ReadAll(conn)

妹子給的回復就在result里,慢慢去琢磨吧……


以上示例并不完整,完整的示例網上到處可見,希望大家能自己寫一寫。
本篇只是粗淺地講了講什么是Socket編程以及基本過程,之后會有更細致地講解(比如:并發)。


作者: PHPBird?
鏈接:http://www.imooc.com/article/1668
來源:慕課網

轉載于:https://www.cnblogs.com/wangjian8888/p/6828117.html

總結

以上是生活随笔為你收集整理的浅谈Socket编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。