This is a creation in Article, where the information may have evolved or changed.
Package Connectionimport ("Encoding/binary" "Errors" "IO" "NET" "Sync" "Time")//maximum message length supportedConstMaxLengthint=1<< +-1 //4294967295var (rheadbytes = [4]byte{0,0,0,0} wheadbytes = [4]byte{0,0,0,0} errmsgread = Errors. New("Message Read length error") Errheadlen = Errors. New("Message head length error") Errmsglen = Errors. New("Message length is no longer in normal range")) var connpool sync. Pool//Gets an object from the object pool, does not exist the declarationFunc newconnection (Conn net. Conn) Conn {c: = Connpool. Get()ifCNT, OK: = C. (*connection); OK {cnt. RWC= connreturnCNT}return&connection{rlen:0, Rwc:conn}}type Conn Interface {Read () (R io. Reader, sizeint, err Error) Write (p []byte) (nint, err Error) Writer (sizeint, R IO. Reader) (n Int64, err Error) remoteaddr () net. AddrLOCALADDR () Net. AddrSetdeadline (T-time. time) Error Setreaddeadline (t time. time) Error Setwritedeadline (t time. time) Error Close () (Err Error)}//define a structure to encapsulate the Conn.Type connectionstruct{Rlenint //Message lengthRWC net. Conn //Original web linkRlock Sync. Mutex //conn Read LockWlock Sync. Mutex //conn Write lock}//This method is used to read header messages.Func ( Self*connection) Rhead () error {n, err: = Self. RWC. Read(rheadbytes[:])ifn! =4|| Err! =Nil{ifErr! =Nil{returnERR}returnErrheadlen} Self. Rlen=int(Binary. Bigendian. Uint32(rheadbytes[:]))return Nil}//This method is used to send header messagesFunc ( Self*connection) Whead (lint) Error {ifL <=0|| L > MaxLength {returnErrmsglen} binary. Bigendian. PutUint32(wheadbytes[:], UInt32 (L)) _, Err: = Self. RWC. Write(wheadbytes[:])returnErr//Header message after parsing. Returns a Io.reader excuse. Used to read data sent from the remote//Encapsulated as Limitread object. To implement the Ioreader interfaceFunc ( Self*connection) Read () (R io. Reader, sizeint, err Error) { Self. Rlock. Lock()ifErr = Self. Rhead(); Err! =Nil{ Self. Rlock. Unlock()return} size = Self. Rlenr = Limitread{r:io. Limitreader( Self. RWC, int64 (size)), Unlock: Self. Rlock. Unlock}return}call the Whead function before sending the message, send the header message, and then send the bodyFunc ( Self*connection) Write (P []byte) (nint, err Error) { Self. Wlock. Lock() Err = Self. Whead(Len (P))ifErr! =Nil{ Self. Wlock. Unlock()return} N, Err = Self. RWC. Write(p) Self. Wlock. Unlock()return}//Send a stream. The length of the stream must be specifiedFunc ( Self*connection) Writer (sizeint, R IO. Reader) (n Int64, err error) { Self. Wlock. Lock() Err = Self. Whead(int(size))ifErr! =Nil{ Self. Wlock. Unlock()return} N, err = IO. Copyn( Self. RWC, R, Int64 (size)) Self. Wlock. Unlock()return}func ( Self*connection) remoteaddr () net. Addr{return Self. RWC. Remoteaddr()}func ( Self*connection) localaddr () net. Addr{return Self. RWC. Localaddr()}func ( Self*connection) Setdeadline (t time. time) Error {return Self. RWC. Setdeadline(t)} Func ( Self*connection) Setreaddeadline (t time. time) Error {return Self. RWC. Setreaddeadline(t)} Func ( Self*connection) Setwritedeadline (t time. time) Error {return Self. RWC. Setwritedeadline(t)} Func ( Self*connection) Close () (err error) {err = Self. RWC. Close() Self. Rlen=0Connpool. Put( Self)return}type Limitreadstruct{R IO. ReaderUnlock func ()}func ( SelfLimitread) Read (P []byte) (nint, err Error) {n, err = Self. R. Read(p)ifErr! =Nil{ Self. Unlock() }returnN, err}
Test the function method:
PackageConnectionImport("FMT" "IO" "NET" "OS" "Testing" "Time")funcTest_conn (t *testing. T) {GoListener ("TCP",": 1789") time. Sleep(1e9) Dial ()}funcDial () {conn, err: = Net. Dial ("TCP","127.0.0.1:1789")ifErr! =Nil{FMT. PRINTLN (ERR)return} c: = Newconnection (conn)deferC.close () C.write ([]byte("Test")) C.write ([]byte("Test")) R, size, err: = C.read ()ifErr! =Nil{FMT. PRINTLN (err, size)return} _, Err = Io. Copy (OS. Stdout, R)ifErr! =Nil&& Err! = Io. EOF {fmt. PRINTLN (ERR)}}funcListener (Proto, addrstring) {lis, err: = Net. Listen (proto, addr)ifErr! =Nil{Panic("Listen Port error:"+ Err. Error ())return}deferLis. Close () for{conn, err: = Lis. Accept ()ifErr! =Nil{time. Sleep(1e7)Continue}GoHandler (conn)}}funcHandler (Conn net. Conn) {c: = Newconnection (Conn) Msgchan: = Make(Chan struct{})deferC.close ()Go func(ChChan struct{}) {<-msgchan F, _: = OS. Open ("Tcp_test.go")deferF.close () info, _: = F.stat () c.writer (int(info.) Size ()), F) C.close ()} (Msgchan) for{r, size, err: = C.read ()ifErr! =Nil{FMT. PRINTLN (ERR)return} N, err: = Io. Copy (OS. Stdout, R)ifErr! =Nil|| n! =Int64(size) {ifErr = = Io. EOF {Continue} FMT. Println ("failed to read data:", err)return} time. Sleep(2e9) Msgchan <-struct{}{} }}