国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

go語言基礎(chǔ)操作---七

這篇具有很好參考價(jià)值的文章主要介紹了go語言基礎(chǔ)操作---七。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

socket簡單介紹—套接字編程

什么是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)的。
go語言基礎(chǔ)操作---七,golang,開發(fā)語言,后端
在TCP/IP協(xié)議中,“IP地址+TCP或UDP端口號”唯一標(biāo)識網(wǎng)絡(luò)通訊中的一個(gè)進(jìn)程?!癐P地址+端口號”就對應(yīng)一個(gè)socket。欲建立連接的兩個(gè)進(jìn)程各自有一個(gè)socket來標(biāo)識,那么這兩個(gè)socket組成的socket pair(套接字對)就唯一標(biāo)識一個(gè)連接因此可以用Socket來描述網(wǎng)絡(luò)連接的一對一關(guān)系。
常用的Socket類型有兩種:流式Socket(SOCK_STREAM)和數(shù)據(jù)報(bào)式Socket(SOCK_DGRAM)流式是一種面向連接的Socket,針對于面向連接的TCP服務(wù)應(yīng)用;數(shù)據(jù)報(bào)式Socket是一種無連接的Socket,對應(yīng)于無連接的UDP服務(wù)應(yīng)用

網(wǎng)絡(luò)應(yīng)用程序設(shè)計(jì)模式

C/S模式
傳統(tǒng)的網(wǎng)絡(luò)應(yīng)用設(shè)計(jì)模式,客戶機(jī)(client)/服務(wù)器(server)模式。需要在通訊兩端各自部署客戶機(jī)和服務(wù)器來完成數(shù)據(jù)通信。
B/S模式
瀏覽器(Browser)/服務(wù)器(Server)模式。只需在一端部署服務(wù)器,而另外一端使用每臺PC都默認(rèn)配置的瀏覽器即可完成數(shù)據(jù)的傳輸。
優(yōu)缺點(diǎn)
對于C/S模式來說,其優(yōu)點(diǎn)明顯??蛻舳宋挥谀繕?biāo)主機(jī)上可以保證性能,將數(shù)據(jù)緩存至客戶端本地,從而提高數(shù)據(jù)傳輸效率。且,一般來說客戶端和服務(wù)器程序由一個(gè)開發(fā)團(tuán)隊(duì)創(chuàng)作,所以他們之間所采用的協(xié)議相對靈活。可以在標(biāo)準(zhǔn)協(xié)議的基礎(chǔ)上根據(jù)需求裁剪及定制。例如,騰訊所采用的通信協(xié)議,即為ftp協(xié)議的修改剪裁版。
因此,傳統(tǒng)的網(wǎng)絡(luò)應(yīng)用程序及較大型的網(wǎng)絡(luò)應(yīng)用程序都首選C/S模式進(jìn)行開發(fā)。如,知名的網(wǎng)絡(luò)游戲魔獸世界。3D畫面,數(shù)據(jù)量龐大,使用C/S模式可以提前在本地進(jìn)行大量數(shù)據(jù)的緩存處理,從而提高觀感。
C/S模式的缺點(diǎn)也較突出。由于客戶端和服務(wù)器都需要有一個(gè)開發(fā)團(tuán)隊(duì)來完成開發(fā)。工作量將成倍提升,開發(fā)周期較長。另外,從用戶角度出發(fā),需要將客戶端安插至用戶主機(jī)上,對用戶主機(jī)的安全性構(gòu)成威脅。這也是很多用戶不愿使用C/S模式應(yīng)用程序的重要原因。
B/S模式相比C/S模式而言,由于它沒有獨(dú)立的客戶端,使用標(biāo)準(zhǔn)瀏覽器作為客戶端,其工作開發(fā)量較小。只需開發(fā)服務(wù)器端即可。另外由于其采用瀏覽器顯示數(shù)據(jù),因此移植性非常好,不受平臺限制。如早期的偷菜游戲,在各個(gè)平臺上都可以完美運(yùn)行。
B/S模式的缺點(diǎn)也較明顯。由于使用第三方瀏覽器,因此網(wǎng)絡(luò)應(yīng)用支持受限。另外,沒有客戶端放到對方主機(jī)上,緩存數(shù)據(jù)不盡如人意,從而傳輸數(shù)據(jù)量受到限制。應(yīng)用的觀感大打折扣。第三,必須與瀏覽器一樣,采用標(biāo)準(zhǔn)http協(xié)議進(jìn)行通信,協(xié)議選擇不靈活。
因此在開發(fā)過程中,模式的選擇由上述各自的特點(diǎn)決定。根據(jù)實(shí)際需求選擇應(yīng)用程序設(shè)計(jì)模式。

TCP的C/S架構(gòu)

go語言基礎(chǔ)操作---七,golang,開發(fā)語言,后端
TCP服務(wù)器代碼編寫

package main

import (
	"fmt"
	"net"
)

func main() {
	//監(jiān)聽nerwork為tcp和udp,address為ip:端口,本地ip地址可以不寫
	listener, err1 := net.Listen("tcp", "127.0.0.1:8080")
	if err1 != nil {
		fmt.Println("err =", err1)
		return
	}
	defer listener.Close() //監(jiān)聽關(guān)閉
	//阻塞等待用戶連接
	conn, err := listener.Accept()
	if err != nil {
		fmt.Println("阻塞:err = ", err)
		return
	}

	//接收用戶請求
	buf := make([]byte, 1024) //1024大小的緩沖區(qū)
	n, err2 := conn.Read(buf)
	if err2 != nil {
		fmt.Println("接收: err2 = ", err2)
		return
	}

	fmt.Println("buf = ", string(buf[:n])) //指定處理的讀多少

	defer conn.Close() //關(guān)閉當(dāng)前用戶連接
}

go語言基礎(chǔ)操作---七,golang,開發(fā)語言,后端

TCP客戶端代碼編寫

package main

import (
	"fmt"
	"net"
)

func main() {

	//主動連接服務(wù)器
	conn, err := net.Dial("tcp", "127.0.0.1:8080")
	if err != nil {
		fmt.Println("err = ", err)
		return
	}

	defer conn.Close() //關(guān)閉

	//發(fā)送數(shù)據(jù)
	conn.Write([]byte("are you ok?"))
}

并發(fā)的C/S模型通信

并發(fā)Server

現(xiàn)在已經(jīng)完成了客戶端與服務(wù)端的通信,但是服務(wù)端只能接收一個(gè)用戶發(fā)送過來的數(shù)據(jù),怎樣接收多個(gè)客戶端發(fā)送過來的數(shù)據(jù),實(shí)現(xiàn)一個(gè)高效的并發(fā)服務(wù)器呢?
Accept()函數(shù)的作用是等待客戶端的鏈接,如果客戶端沒有鏈接,該方法會阻塞。如果有客戶端鏈接,那么該方法返回一個(gè)Socket負(fù)責(zé)與客戶端進(jìn)行通信。所以,每來一個(gè)客戶端,該方法就應(yīng)該返回一個(gè)Socket與其通信,因此,可以使用一個(gè)死循環(huán),將Accept()調(diào)用過程包裹起來。
需要注意的是,實(shí)現(xiàn)并發(fā)處理多個(gè)客戶端數(shù)據(jù)的服務(wù)器,就需要針對每一個(gè)客戶端連接,單獨(dú)產(chǎn)生一個(gè)Socket,并創(chuàng)建一個(gè)單獨(dú)的goroutine與之完成通信。

簡單版并發(fā)服務(wù)器

package main

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

// 處理用戶請求
func HandleConn(conn net.Conn) {
	//函數(shù)調(diào)用完畢,自動關(guān)閉conn
	defer conn.Close()

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

	//讀取用戶數(shù)據(jù)
	buf := make([]byte, 2048)
	for true {
		//讀取用戶數(shù)據(jù)
		read, err := conn.Read(buf)
		if err != nil {
			//read tcp 127.0.0.1:8080->127.0.0.1:56933:
			//wsarecv: An existing connection was forcibly closed by the remote host.
			fmt.Println("err = ", err)
			return
		}
		fmt.Printf("[%s]: = %s\n", addr, string(buf[:read])) //read為讀取數(shù)據(jù)的個(gè)數(shù)
		fmt.Println("len = ", len(string(buf[:read])))
		if "exit" == string(buf[:read-1]) {
			fmt.Println(addr, "exit")
			return
		}
		//把數(shù)據(jù)轉(zhuǎn)化為大寫,再給用戶發(fā)送
		conn.Write([]byte(strings.ToUpper(string(buf[:read]))))
	}
}

func main() {
	//監(jiān)聽nerwork為tcp和udp,address為ip:端口,本地ip地址可以不寫
	listener, err1 := net.Listen("tcp", "127.0.0.1:8080")
	if err1 != nil {
		fmt.Println("err =", err1)
		return
	}
	defer listener.Close() //監(jiān)聽關(guān)閉

	//接收多個(gè)用戶
	for true {
		conn, err := listener.Accept() //等待客戶端的鏈接,如果客戶端沒有鏈接,該方法會阻塞
		if err != nil {
			fmt.Println("err = ", err)
			return
		}

		//處理用戶請求,新建一個(gè)協(xié)程,每來一個(gè)就單獨(dú)為它獲取
		go HandleConn(conn)
	}
}

go語言基礎(chǔ)操作---七,golang,開發(fā)語言,后端

并發(fā)Client

客戶端不僅需要持續(xù)的向服務(wù)端發(fā)送數(shù)據(jù),同時(shí)也要接收從服務(wù)端返回的數(shù)據(jù)。因此可將發(fā)送和接收放到不同的協(xié)程中。
主協(xié)程循環(huán)接收服務(wù)器回發(fā)的數(shù)據(jù)(該數(shù)據(jù)應(yīng)已轉(zhuǎn)換為大寫),并打印至屏幕;子協(xié)程循環(huán)從鍵盤讀取用戶輸入數(shù)據(jù),寫給服務(wù)器。讀取鍵盤輸入可使用 os.Stdin.Read(str)。定義切片str,將讀到的數(shù)據(jù)保存至str中。
這樣,客戶端也實(shí)現(xiàn)了多任務(wù)。

客戶端即可輸入也可接收服務(wù)器回復(fù)

package main

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

func main() {

	//主動連接服務(wù)器
	conn, err := net.Dial("tcp", "127.0.0.1:8080")
	if err != nil {
		fmt.Println("net Dial err = ", err)
		return
	}

	//main調(diào)用完畢,關(guān)閉連接
	defer conn.Close() //關(guān)閉

	//接收服務(wù)器回復(fù)的數(shù)據(jù),新任務(wù)
	go func() {
		//從鍵盤輸入內(nèi)容,給服務(wù)器發(fā)送內(nèi)容
		str := make([]byte, 1024)
		for true {
			n, err2 := os.Stdin.Read(str) //從鍵盤讀取內(nèi)容,放在str
			if err2 != nil {
				fmt.Println("os.Stdin.err = ", err)
				return
			}
			//把輸入的內(nèi)容給服務(wù)器發(fā)送
			conn.Write(str[:n])
		}
	}()
	//切片緩存
	buf := make([]byte, 1024)
	//不停地接收
	for true {
		n, err := conn.Read(buf) //接收服務(wù)器的請求
		if err != nil {
			fmt.Println("conn.Read err = ", err)
			return
		}
		fmt.Println(string(buf[:n])) //打印接收到的內(nèi)容,轉(zhuǎn)換為字符串再打印
	}
}

go語言基礎(chǔ)操作---七,golang,開發(fā)語言,后端

TCP通信

下圖是一次TCP通訊的時(shí)序圖。TCP連接建立斷開。包含大家熟知的三次握手和四次握手。
go語言基礎(chǔ)操作---七,golang,開發(fā)語言,后端
三次握手:
所謂三次握手(Three-Way Handshake)即建立TCP連接,就是指建立一個(gè)TCP連接時(shí),需要客戶端和服務(wù)端總共發(fā)送3個(gè)包以確認(rèn)連接的建立。好比兩個(gè)人在打電話:
Client:“喂,你聽得到嗎?”
Server:“我聽得到,你聽得到我嗎?”
Client:“我能聽到你,今天balabala…”
建立連接(三次握手)的過程:
1.客戶端發(fā)送一個(gè)帶SYN標(biāo)志的TCP報(bào)文到服務(wù)器。這是上圖中三次握手過程中的段1??蛻舳税l(fā)出SYN位表示連接請求。序號是1000,這個(gè)序號在網(wǎng)絡(luò)通訊中用作臨時(shí)的地址,每發(fā)一個(gè)數(shù)據(jù)字節(jié),這個(gè)序號要加1,這樣在接收端可以根據(jù)序號排出數(shù)據(jù)包的正確順序,也可以發(fā)現(xiàn)丟包的情況。
另外,規(guī)定SYN位和FIN位也要占一個(gè)序號,這次雖然沒發(fā)數(shù)據(jù),但是由于發(fā)了SYN位,因此下次再發(fā)送應(yīng)該用序號1001。
mss表示最大段尺寸,如果一個(gè)段太大,封裝成幀后超過了鏈路層的最大長度,就必須在IP層分片,為了避免這種情況,客戶端聲明自己的最大段尺寸,建議服務(wù)器端發(fā)來的段不要超過這個(gè)長度。
2.服務(wù)器端回應(yīng)客戶端,是三次握手中的第2個(gè)報(bào)文段,同時(shí)帶ACK標(biāo)志和SYN標(biāo)志。表示對剛才客戶端SYN的回應(yīng);同時(shí)又發(fā)送SYN給客戶端,詢問客戶端是否準(zhǔn)備好進(jìn)行數(shù)據(jù)通訊。
服務(wù)器發(fā)出段2,也帶有SYN位,同時(shí)置ACK位表示確認(rèn),確認(rèn)序號是1001,表示“我接收到序號1000及其以前所有的段,請你下次發(fā)送序號為1001的段”,也就是應(yīng)答了客戶端的連接請求,同時(shí)也給客戶端發(fā)出一個(gè)連接請求,同時(shí)聲明最大尺寸為1024。
3.客戶必須再次回應(yīng)服務(wù)器端一個(gè)ACK報(bào)文,這是報(bào)文段3。
客戶端發(fā)出段3,對服務(wù)器的連接請求進(jìn)行應(yīng)答,確認(rèn)序號是8001。在這個(gè)過程中,客戶端和服務(wù)器分別給對方發(fā)了連接請求,也應(yīng)答了對方的連接請求,其中服務(wù)器的請求和應(yīng)答在一個(gè)段中發(fā)出。
因此一共有三個(gè)段用于建立連接,稱為“三方握手”。在建立連接的同時(shí),雙方協(xié)商了一些信息,例如,雙方發(fā)送序號的初始值、最大段尺寸等。
數(shù)據(jù)傳輸?shù)倪^程:
1.客戶端發(fā)出段4,包含從序號1001開始的20個(gè)字節(jié)數(shù)據(jù)。
2.服務(wù)器發(fā)出段5,確認(rèn)序號為1021,對序號為1001-1020的數(shù)據(jù)表示確認(rèn)收到,同時(shí)請求發(fā)送序號1021開始的數(shù)據(jù),服務(wù)器在應(yīng)答的同時(shí)也向客戶端發(fā)送從序號8001開始的10個(gè)字節(jié)數(shù)據(jù)。
3.客戶端發(fā)出段6,對服務(wù)器發(fā)來的序號為8001-8010的數(shù)據(jù)表示確認(rèn)收到,請求發(fā)送序號8011開始的數(shù)據(jù)。
在數(shù)據(jù)傳輸過程中,ACK和確認(rèn)序號是非常重要的,應(yīng)用程序交給TCP協(xié)議發(fā)送的數(shù)據(jù)會暫存在TCP層的發(fā)送緩沖區(qū)中,發(fā)出數(shù)據(jù)包給對方之后,只有收到對方應(yīng)答的ACK段才知道該數(shù)據(jù)包確實(shí)發(fā)到了對方,可以從發(fā)送緩沖區(qū)中釋放掉了,如果因?yàn)榫W(wǎng)絡(luò)故障丟失了數(shù)據(jù)包或者丟失了對方發(fā)回的ACK段,經(jīng)過等待超時(shí)后TCP協(xié)議自動將發(fā)送緩沖區(qū)中的數(shù)據(jù)包重發(fā)。
四次揮手:
所謂四次揮手(Four-Way-Wavehand)即終止TCP連接,就是指斷開一個(gè)TCP連接時(shí),需要客戶端和服務(wù)端總共發(fā)送4個(gè)包以確認(rèn)連接的斷開。在socket編程中,這一過程由客戶端或服務(wù)器任一方執(zhí)行close來觸發(fā)。好比兩個(gè)人打完電話要掛斷:
Client:“我要說的事情都說完了,我沒事了。掛啦?”
Server:“等下,我還有一個(gè)事兒。Balabala…”
Server:“好了,我沒事兒了。掛了啊。”
Client:“ok!拜拜”
關(guān)閉連接(四次握手)的過程:
由于TCP連接是全雙工的,因此每個(gè)方向都必須單獨(dú)進(jìn)行關(guān)閉。這原則是當(dāng)一方完成它的數(shù)據(jù)發(fā)送任務(wù)后就能發(fā)送一個(gè)FIN來終止這個(gè)方向的連接。收到一個(gè) FIN只意味著這一方向上沒有數(shù)據(jù)流動,一個(gè)TCP連接在收到一個(gè)FIN后仍能發(fā)送數(shù)據(jù)。首先進(jìn)行關(guān)閉的一方將執(zhí)行主動關(guān)閉,而另一方執(zhí)行被動關(guān)閉。
1.客戶端發(fā)出段7,F(xiàn)IN位表示關(guān)閉連接的請求。
2.服務(wù)器發(fā)出段8,應(yīng)答客戶端的關(guān)閉連接請求。
3.服務(wù)器發(fā)出段9,其中也包含F(xiàn)IN位,向客戶端發(fā)送關(guān)閉連接請求。
4.客戶端發(fā)出段10,應(yīng)答服務(wù)器的關(guān)閉連接請求。
建立連接的過程是三次握手,而關(guān)閉連接通常需要4個(gè)段,服務(wù)器的應(yīng)答和關(guān)閉連接請求通常不合并在一個(gè)段中,因?yàn)橛羞B接半關(guān)閉的情況,這種情況下客戶端關(guān)閉連接之后就不能再發(fā)送數(shù)據(jù)給服務(wù)器了,但是服務(wù)器還可以發(fā)送數(shù)據(jù)給客戶端,直到服務(wù)器也關(guān)閉連接為止。

UDP通信

在之前的案例中,我們一直使用的是TCP協(xié)議來編寫Socket的客戶端與服務(wù)端。其實(shí)也可以使用UDP協(xié)議來編寫Socket的客戶端與服務(wù)端。
UDP服務(wù)器
由于UDP是“無連接”的,所以,服務(wù)器端不需要額外創(chuàng)建監(jiān)聽套接字,只需要指定好IP和port,然后監(jiān)聽該地址,等待客戶端與之建立連接,即可通信。
創(chuàng)建監(jiān)聽地址:
func ResolveUDPAddr(network, address string) (*UDPAddr, error)
創(chuàng)建監(jiān)聽連接:
func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error)
接收udp數(shù)據(jù):
func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error)
寫出數(shù)據(jù)到udp:
func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error)

文件傳輸原理

go語言基礎(chǔ)操作---七,golang,開發(fā)語言,后端

UDP與TCP的差異

go語言基礎(chǔ)操作---七,golang,開發(fā)語言,后端

os.Stat的使用

package main

import (
	"fmt"
	"os"
)

func main() {
	list := os.Args
	fmt.Println(len(list))
	if len(list) != 2 {
		fmt.Println("useage :xxx file")
		return
	}

	for i, s := range list {
		fmt.Println(i, s)
	}
	fileName := list[1]
	fmt.Printf("fileName = %s\n", fileName)

	//Stat返回一個(gè)描述name指定的文件對象的FileInfo。如果指定的文件對象是一個(gè)符號鏈接,
	//返回的FileInfo描述該符號鏈接指向的文件的信息,本函數(shù)會嘗試跳轉(zhuǎn)該鏈接。如果出錯(cuò),返回的錯(cuò)誤值為*PathError類型。
	//過濾路徑
	info, err := os.Stat(fileName)

	if err != nil {
		fmt.Println("err = ", err)
	}
	fmt.Println("name = ", info.Name()) //name =  01_昨日回顧.mp4
	fmt.Println("size = ", info.Size()) //size =  67010611
}

go語言基礎(chǔ)操作---七,golang,開發(fā)語言,后端文章來源地址http://www.zghlxwxcb.cn/news/detail-709294.html

傳輸文件:發(fā)送方

package main

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

func sendFile(path string, conn net.Conn) {
	//以只讀方式打開文件
	file, err := os.Open(path)
	if err != nil {
		fmt.Println("send Open err = ", err)
		return
	}

	defer file.Close()

	//讀文件內(nèi)容,讀多少發(fā)多少,一點(diǎn)不差
	buf := make([]byte, 1024*4)
	for true {
		read, err := file.Read(buf) //從文件讀取內(nèi)容
		if err != nil {
			if err == io.EOF {
				fmt.Println("文件發(fā)送完畢")
			} else {
				fmt.Println("send Rend err = ", err)
			}
			return
		}
		//發(fā)送內(nèi)容
		conn.Write(buf[:read]) //給服務(wù)器發(fā)送內(nèi)容
	}
}

func main() {

	//提示輸入文件
	fmt.Println("請輸入需要傳輸?shù)奈募? ")
	var path string
	_, err := fmt.Scan(&path)
	if err != nil {
		fmt.Println("Scan open err = ", err)
		return
	}

	//獲取文件名
	fileInfo, err := os.Stat(path)
	if err != nil {
		fmt.Println("os.Stat err = ", err)
		return
	}

	//主動連接服務(wù)器
	conn, err := net.Dial("tcp", "127.0.0.1:8000")
	if err != nil {
		fmt.Println("net.Dial err = ", err)
		return
	}

	defer conn.Close()

	//給接收方,先發(fā)送文件名
	_, err = conn.Write([]byte(fileInfo.Name()))
	if err != nil {
		fmt.Println("conn.write err = ", err)
		return
	}

	//接收對方的回復(fù),如果回復(fù)ok,說明對方準(zhǔn)備好,可以發(fā)文件
	buf := make([]byte, 1024)
	readSize, err := conn.Read(buf)
	if err != nil {
		fmt.Println("conn.Read err = ", err)
		return
	}

	if "ok" == string(buf[:readSize]) {
		//發(fā)送文件內(nèi)容
		sendFile(path, conn)
	}
}

傳輸文件:接收方

package main

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

// RecvFile 接收文件內(nèi)容
func RecvFile(fileName string, conn net.Conn) {
	//新建文件
	file, err := os.Create(fileName)
	if err != nil {
		fmt.Println("os create err =", err)
		return
	}

	buf := make([]byte, 1024*4)

	//接收多少,寫多少,一點(diǎn)不差
	for true {
		readSize, err := conn.Read(buf) //接收對方發(fā)過來的文件內(nèi)容
		if err != nil {
			if err == io.EOF {
				fmt.Println("文件接收完畢")
			} else {
				fmt.Println("conn read err =", err)
			}
			return
		}
		if readSize == 0 {
			fmt.Println("n == 0 文件接收完畢")
			return
		}

		file.Write(buf[:readSize])
	}
}

func main() {
	//監(jiān)聽
	listener, err := net.Listen("tcp", "127.0.0.1:8000")
	if err != nil {
		fmt.Println("net listener err = ", err)
		return
	}

	defer listener.Close()

	//阻塞等待用戶連接
	conn, err := listener.Accept()
	if err != nil {
		fmt.Println("listener accept err =", err)
		return
	}

	defer conn.Close()
	buf := make([]byte, 1024)

	//讀取對方發(fā)送的文件名
	readSize, err := conn.Read(buf)
	if err != nil {
		fmt.Println("conn read err =", err)
		return
	}

	fileName := string(buf[:readSize])

	//回復(fù)"ok"
	_, err1 := conn.Write([]byte("ok"))
	if err1 != nil {
		return
	}

	//接收文件內(nèi)容
	RecvFile(fileName, conn)
}

到了這里,關(guān)于go語言基礎(chǔ)操作---七的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Go 基礎(chǔ)篇】探索Go語言中Map的神奇操作

    【Go 基礎(chǔ)篇】探索Go語言中Map的神奇操作

    嗨,Go語言的學(xué)習(xí)者們!在編程世界中,Map是一個(gè)強(qiáng)大而又有趣的工具,它可以幫助我們高效地存儲和操作鍵值對數(shù)據(jù)。Map就像是一本字典,可以讓我們根據(jù)(鍵)快速找到對應(yīng)的信息(值)。在本文中,我們將探索Go語言中Map的各種操作,包括增加、查找、刪除、遍歷

    2024年02月10日
    瀏覽(34)
  • 100天精通Golang(基礎(chǔ)入門篇)——第12天:深入解析Go語言中的集合(Map)及常用函數(shù)應(yīng)用

    100天精通Golang(基礎(chǔ)入門篇)——第12天:深入解析Go語言中的集合(Map)及常用函數(shù)應(yīng)用

    ?? 博主 libin9iOak帶您 Go to Golang Language.? ?? 個(gè)人主頁——libin9iOak的博客?? ?? 《面試題大全》 文章圖文并茂??生動形象??簡單易學(xué)!歡迎大家來踩踩~?? ?? 《IDEA開發(fā)秘籍》學(xué)會IDEA常用操作,工作效率翻倍~?? ?? 希望本文能夠給您帶來一定的幫助??文章粗淺,敬請批

    2024年02月12日
    瀏覽(27)
  • 【Go】Go語言開發(fā)0基礎(chǔ)7天入門 - 筆記

    【Go】Go語言開發(fā)0基礎(chǔ)7天入門 - 筆記

    課程來源:【路飛學(xué)城】-黑金年卡VIP課程 課程名稱:GO語言開發(fā)0基礎(chǔ)7天入門 講師:【 前汽車之家架構(gòu)師 】Wusir-銀角大王 官網(wǎng):點(diǎn)擊進(jìn)入 集python簡潔 + C語言性能 詳情點(diǎn)擊 編程語言 實(shí)戰(zhàn)經(jīng)驗(yàn) 源碼 并發(fā)架構(gòu) 新語言觸類旁通 1.1 開篇介紹(必看) 1.2 環(huán)境搭建前戲 1.3 mac系統(tǒng)G

    2024年02月16日
    瀏覽(30)
  • Excelize Go語言操作 Office Excel文檔基礎(chǔ)庫

    Excelize Go語言操作 Office Excel文檔基礎(chǔ)庫

    Excelize 是 Go 語言編寫的用于操作 Office Excel 文檔基礎(chǔ)庫,基于 ECMA-376,ISO/IEC 29500 國際標(biāo)準(zhǔn)??梢允褂盟鼇碜x取、寫入由 Microsoft Excel? 2007 及以上版本創(chuàng)建的電子表格文檔。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多種文檔格式,高度兼容帶有樣式、圖片(表)、透視表、切片器等復(fù)雜

    2024年02月12日
    瀏覽(15)
  • 【Go 基礎(chǔ)篇】Go語言包詳解:模塊化開發(fā)與代碼復(fù)用

    在Go語言中, 包(Package) 是一種用于組織代碼的機(jī)制,用于將相關(guān)的函數(shù)、類型和變量等組織在一起,以便于模塊化開發(fā)和代碼復(fù)用。包的使用能夠使程序結(jié)構(gòu)更加清晰、可維護(hù)性更高,同時(shí)也是Go語言強(qiáng)調(diào)的一項(xiàng)重要特性。本篇博客將深入探討Go語言中包的相關(guān)知識,包括

    2024年02月11日
    瀏覽(88)
  • go語言從0基礎(chǔ)到安全項(xiàng)目開發(fā)實(shí)戰(zhàn)

    go語言從0基礎(chǔ)到安全項(xiàng)目開發(fā)實(shí)戰(zhàn)

    搭建環(huán)境比較簡單 到以下鏈接下 Go下載 - Go語言中文網(wǎng) - Golang中文社區(qū) 下載windows版本64位zip包 https://studygolang.com/dl/golang/go1.20.7.windows-amd64.zip 不配置的話就只能在bin目錄下才能運(yùn)行g(shù)o命令 創(chuàng)建test.go文件 然后代碼如下 編譯運(yùn)行? 兩種方式編譯運(yùn)行代碼 1.先 go build test.go編譯成

    2024年02月13日
    瀏覽(17)
  • Go語言 -- Web開發(fā)基礎(chǔ)學(xué)習(xí) net/http包

    Go語言 -- Web開發(fā)基礎(chǔ)學(xué)習(xí) net/http包

    Go 是一個(gè)開源的編程語言,它能讓構(gòu)造簡單、可靠且高效的軟件變得容易。 Go語言最擅長的領(lǐng)域就是Web開發(fā),此貼是本人入門完go語法基礎(chǔ)后學(xué)習(xí)Web開發(fā)的學(xué)習(xí)筆記。 新建go文件hello_world.go 寫入: 在命令行運(yùn)行: go run ./hello_world.go 可以發(fā)現(xiàn)控制臺輸出以下信息 通過上述代碼

    2024年02月06日
    瀏覽(22)
  • 【go語言基礎(chǔ)】go中的方法

    先思考一個(gè)問題,什么是方法,什么是函數(shù)? 方法是從屬于某個(gè)結(jié)構(gòu)體或者非結(jié)構(gòu)體的。在func這個(gè)和方法名中間加了一個(gè)特殊的接收器類型,這個(gè)接收器可以是結(jié)構(gòu)體類型的或者是非結(jié)構(gòu)體類型的。從屬的結(jié)構(gòu)體獲取該方法。 函數(shù)則沒有這種從屬關(guān)系。 小結(jié): 大多

    2024年02月13日
    瀏覽(21)
  • Go語言基礎(chǔ)(一)

    本文檔參考golang官方文檔以及一些教程書籍,若文檔有錯(cuò)誤,歡迎issue ?? https://go.dev/doc/tutorial/ 參考書籍《Go語言開發(fā)實(shí)戰(zhàn)》 Go語言是Google公司發(fā)布的一種靜態(tài)型、編譯型的開源編程語言,是新時(shí)代的 C語言 。Go語言已經(jīng)成為 云計(jì)算時(shí)代 的重要基礎(chǔ)編程語言。 2012年3月28日,

    2024年02月06日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包