[Golang]Socket编程01----实现基本功能的Client和Server

码农小骚年 · · 3147 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

支持多连接。

Server运行之后,进入Accept阻塞状态。Accept得到一个Conn之后,开启一个协程,分别有两个协程阻塞在Read和Write。当Read一个数据之后,将Read得到的数据写入readChannel中,之后再对其进行处理。在writeChannel得到一个数据之后,向Conn写入数据。

Client运行后,接入Server,之后开启两个协程阻塞在Read和Write的Channel中。在Scan得到一个数据之后,向writeChannel写入数据,唤醒阻塞的协程向Conn中写入数据。当Server中有数据返回时,read协程被唤醒,将数据写入readChannel中。

 

当然,还有诸多细节要处理。比如Conn的关闭在什么时候等等。

 

客户端源码

package client

import (
	"net"
	"git.oschina.net/sdlszjb/unix_socket/errs"
	"fmt"
)

func StartClient1() {
	tcpAddress, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:1300")
	if err != nil {
		errs.Error_exit(err)
	}
	conn, err := net.DialTCP("tcp", nil, tcpAddress)
	if err != nil {
		errs.Error_exit(err)
	}

	writeChan := make(chan []byte, 1024)
	readChan := make(chan []byte, 1024)

	go writeConnection(conn, writeChan)
	go readConnection(conn, readChan)

	//go handleReadChannel(readChan)

	for {
		var s string
		fmt.Scan(&s)
		writeChan <- []byte(s)
	}

}

func readConnection(conn *net.TCPConn, channel chan []byte) {
	defer conn.Close()

	buffer := make([]byte, 2048)
	for {
		n, err := conn.Read(buffer)
		if err != nil {
			errs.Error_print(err)
			return
		}
		println("Received from:", conn.RemoteAddr(), string(buffer[:n]))
		//channel <- buffer[:n]
	}

}

func writeConnection(conn *net.TCPConn, channel chan []byte) {
	defer conn.Close()
	for {
		select {
		case data := <- channel:
			_, err := conn.Write(data)
			if err != nil {
				errs.Error_exit(err)
			}
			println("Write to:", conn.RemoteAddr(), string(data))
		}
	}
}

服务端代码:

package server

import (
	"net"
	"git.oschina.net/sdlszjb/unix_socket/errs"
	"fmt"
)

var client_num int = 0

func StartServer1() {
	l, err := net.Listen("tcp", ":1300")
	if err != nil {
		errs.Error_exit(err)
	}
	defer l.Close()

	for {
		conn, err := l.Accept()
		if err != nil {
			errs.Error_print(err)
			continue
		}
		client_num++
		fmt.Printf("A new Connection %d.\n", client_num)
		go handlerConnection(conn)
	}
}
func handlerConnection(conn net.Conn) {
	defer closeConnection(conn)

	readChannel := make(chan []byte, 1024)
	writeChannel := make(chan []byte, 1024)

	go readConnection(conn, readChannel)
	go writeConnection(conn, writeChannel)


	for {
		select {
		case data := <- readChannel:
			if string(data) == "bye" {
				return
			}
			writeChannel <- append([]byte("Back"), data...)
		}
	}

}

func writeConnection(conn net.Conn, channel chan []byte) {
	for {
		select {
		case data := <- channel:
			println("Write:", conn.RemoteAddr().String(), string(data))
			_, err := conn.Write(data)
			if err != nil {
				errs.Error_print(err)
				return
			}
		}
	}

}
func readConnection(conn net.Conn, channel chan []byte) {

	buffer := make([]byte, 2048)

	for {
		n, err := conn.Read(buffer)
		if err != nil {
			errs.Error_print(err)
			channel <- []byte("bye")	//这里须要进一步改进!
			break
		}
		println("Recei:", conn.RemoteAddr().String(), string(buffer[:n]))
		channel <- buffer[:n]
	}
}

func closeConnection(conn net.Conn) {

	conn.Close()
	client_num--
	fmt.Printf("Now, %d connections is alve.\n", client_num)

}

 


有疑问加站长微信联系(非本文作者)

本文来自:开源中国博客

感谢作者:码农小骚年

查看原文:[Golang]Socket编程01----实现基本功能的Client和Server

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:1006366459

3147 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传