go 語言socket 編程

簡介

Socket的圆,英文含義是【插座、插孔】半火,一般稱之為套接字越妈,用于描述IP地址和端口∨ヌ牵可以實(shí)現(xiàn)不同程序間的數(shù)據(jù)通信梅掠。

Socket起源于Unix,而Unix基本哲學(xué)之一就是“一切皆文件”店归,都可以用“打開open –> 讀寫write/read –> 關(guān)閉close”模式來操作瓤檐。Socket就是該模式的一個(gè)實(shí)現(xiàn),網(wǎng)絡(luò)的Socket數(shù)據(jù)傳輸是一種特殊的I/O娱节,Socket也是一種文件描述符挠蛉。Socket也具有一個(gè)類似于打開文件的函數(shù)調(diào)用:Socket(),該函數(shù)返回一個(gè)整型的Socket描述符肄满,隨后的連接建立谴古、數(shù)據(jù)傳輸?shù)炔僮鞫际峭ㄟ^該Socket實(shí)現(xiàn)的。

  • 網(wǎng)絡(luò)上的兩個(gè)程序通過一個(gè)雙向的通信連接實(shí)現(xiàn)數(shù)據(jù)的交換稠歉,這個(gè)連接的一端稱為一個(gè)socket掰担。
  • 建立網(wǎng)絡(luò)通信連接至少要一對端口號(socket)。socket本質(zhì)是編程接口(API)怒炸,對TCP/IP的封裝带饱,TCP/IP也要提供可供程序員做網(wǎng)絡(luò)開發(fā)所用的接口,這就是Socket編程接口阅羹;HTTP是轎車勺疼,提供了封裝或者顯示數(shù)據(jù)的具體形式;Socket是發(fā)動(dòng)機(jī)捏鱼,提供了網(wǎng)絡(luò)通信的能力执庐。
  • Socket的英文原義是“孔”或“插座”。作為BSD UNIX的進(jìn)程通信機(jī)制导梆,取后一種意思轨淌。通常也稱作"套接字"迂烁,用于描述IP地址和端口,是一個(gè)通信鏈的句柄递鹉,可以用來實(shí)現(xiàn)不同虛擬機(jī)或不同計(jì)算機(jī)之間的通信盟步。每種服務(wù)都打開一個(gè)Socket,并綁定到一個(gè)端口上躏结,不同的端口對應(yīng)于不同的服務(wù)址芯。Socket正如其英文原意那樣,像一個(gè)多孔插座窜觉。插座是用來給插頭提供一個(gè)接口讓其通電的谷炸,此時(shí)我們就可以將插座當(dāng)做一個(gè)服務(wù)端,不同的插頭當(dāng)做客戶端。
服務(wù)端
package main

import (
    "fmt"
    "net"
    "strings"
)

func main() {
    listener ,err := net.Listen("tcp",":8000")
    if err != nil {
        fmt.Println("listen err :",err)
    }

    defer listener.Close()
    fmt.Println("等待客戶端連接...")

    // 接收多個(gè)用戶
    for {
        conn ,err := listener.Accept()
        if err != nil {
            fmt.Println("err=",err)
            return
        }
        go HandleConn(conn)
    }

/*  conn, err := listener.Accept()
    if err != nil {
        fmt.Println("accept err:",err)
    }
    defer conn.Close()
    fmt.Println("客戶端與服務(wù)器連接建立成功...")

    buf := make([]byte,1024)

    n,err := conn.Read(buf)

    if err != nil {
        fmt.Println("read err: ",err)
    }
    _,err = conn.Write([]byte("收到了"))
    if err != nil {
        fmt.Println("收到了:",err)
    }
    fmt.Println("服務(wù)器讀到數(shù)據(jù):",string(buf[:n]))*/
}

func HandleConn(conn net.Conn) {
    //函數(shù)調(diào)用完畢禀挫,自動(dòng)關(guān)閉conn
    defer conn.Close()

    //獲取客戶端的網(wǎng)絡(luò)地址信息
    addr := conn.RemoteAddr().String()
    fmt.Println(addr, " conncet sucessful")

    buf := make([]byte, 2048)


    //把數(shù)據(jù)轉(zhuǎn)換為大寫旬陡,再給用戶發(fā)送 這個(gè)地方for 是為了客戶端和服務(wù)端保持連接不中斷
    for {
        //讀取用戶數(shù)據(jù)
        n, err := conn.Read(buf)
        if err != nil {
            fmt.Println("err = ", err)
            return
        }
        fmt.Printf("[%s]: %s\n",  addr,  string(buf[:n]))
        fmt.Println("len = ", len(string(buf[:n])))

        //if "exit" == string(buf[:n-1]) {  // nc測試,發(fā)送時(shí)语婴,只有 \n
        if  "exit" == string(buf[:n-1]) {  // 自己寫的客戶端測試, 發(fā)送時(shí)描孟,多了2個(gè)字符, "\r\n"
            fmt.Println(addr, " exit")
            return
        }
        fmt.Println("ok",string(buf[:n]))
        conn.Write([]byte(strings.ToUpper(string(buf[:n]))))
    }
}

客戶端

package main

import (
    "fmt"
    "net"
    "os"
)

func main() {
    conn,err := net.Dial("tcp","127.0.0.1:8000")

    if err != nil {
        fmt.Println("Dial err:",err)
    }

    defer conn.Close()


    // 啟動(dòng)子協(xié)程,接收用戶鍵盤輸入
    go func() {
        str := make([]byte, 1024)         // 創(chuàng)建用于存儲用戶鍵盤輸入數(shù)據(jù)的切片緩沖區(qū)砰左。
        for {                             // 反復(fù)讀取
            n, err :=os.Stdin.Read(str)        // 獲取用戶鍵盤輸入
            if err != nil {
                fmt.Println("os.Stdin.Read err:", err)
                return
            }
            // 將從鍵盤讀到的數(shù)據(jù)匿醒,發(fā)送給服務(wù)器
            _, err = conn.Write(str[:n])       // 讀多少,寫多少
            if err != nil {
                fmt.Println("conn.Write err:", err)
                return
            }
        }
    }()

    // 主協(xié)程缠导,接收服務(wù)器回發(fā)數(shù)據(jù)廉羔,打印至屏幕
    buf := make([]byte, 1024)                // 定義用于存儲服務(wù)器回發(fā)數(shù)據(jù)的切片緩沖區(qū)
    for {
        n, err := conn.Read(buf)          // 從通信 socket 中讀數(shù)據(jù),存入切片緩沖區(qū)
        if err != nil {
            fmt.Println("conn.Read err:", err)
            return
        }
        fmt.Printf("服務(wù)器回發(fā):%s\n", string(buf[:n]))
    }

/*  n,err := conn.Write([]byte("are you ok"))
    if err != nil {
        fmt.Println("write err:",err)
    }
    fmt.Println(n)

    buf := make([]byte,1024)

    n,err = conn.Read(buf)

    if err != nil {
        fmt.Println("read err: ",err)
    }
    fmt.Println("客戶端讀到數(shù)據(jù):",string(buf[:n]))*/
}

參考文獻(xiàn)

http://www.reibang.com/p/dc8e23de0367

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末僻造,一起剝皮案震驚了整個(gè)濱河市憋他,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌髓削,老刑警劉巖竹挡,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異立膛,居然都是意外死亡揪罕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門宝泵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來好啰,“玉大人,你說我怎么就攤上這事鲁猩】补郑” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵廓握,是天一觀的道長搅窿。 經(jīng)常有香客問我,道長隙券,這世上最難降的妖魔是什么男应? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮娱仔,結(jié)果婚禮上沐飘,老公的妹妹穿的比我還像新娘。我一直安慰自己牲迫,他們只是感情好耐朴,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盹憎,像睡著了一般筛峭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上陪每,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天影晓,我揣著相機(jī)與錄音,去河邊找鬼檩禾。 笑死挂签,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的盼产。 我是一名探鬼主播饵婆,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼戏售!你這毒婦竟也來了啦辐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤蜈项,失蹤者是張志新(化名)和其女友劉穎芹关,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體紧卒,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡侥衬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了跑芳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片轴总。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖博个,靈堂內(nèi)的尸體忽然破棺而出怀樟,到底是詐尸還是另有隱情,我是刑警寧澤盆佣,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布往堡,位于F島的核電站械荷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏虑灰。R本人自食惡果不足惜吨瞎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望穆咐。 院中可真熱鬧颤诀,春花似錦、人聲如沸对湃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拍柒。三九已至心傀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間斤儿,已是汗流浹背剧包。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留往果,地道東北人疆液。 一個(gè)月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像陕贮,于是被迫代替她去往敵國和親堕油。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Socket編程 什么是Socket Socket肮之,英文含義是【插座掉缺、插孔】,一般稱之為套接字戈擒,用于描述IP地址和...
    王玉偉的偉閱讀 7,789評論 0 2
  • 1. 概述 Socket 起源于 Unix眶明,而 Unix 基本哲學(xué)之一就是“一切皆文件”,都可以用“打開 open...
    楚江云閱讀 831評論 0 0
  • 網(wǎng)絡(luò)編程 一.楔子 你現(xiàn)在已經(jīng)學(xué)會了寫python代碼,假如你寫了兩個(gè)python文件a.py和b.py柑土,分別去運(yùn)...
    go以恒閱讀 1,995評論 0 6
  • 說明 本文 翻譯自 realpython 網(wǎng)站上的文章教程 Socket Programming in Pytho...
    keelii閱讀 2,109評論 0 16
  • 欲知前事如何蜀肘,可以點(diǎn)擊作者頭像收看。急更中稽屏,敬請期待情節(jié)發(fā)展扮宠。 曼姝在街上一步一步地走著,她本來可以回到自己當(dāng)初寓...
    婉青婉青閱讀 523評論 2 0