tcp编程之socket

socket :

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。
Socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原义那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务。
IP + PORT
ip:用来唯一标识一台主机
port:用来唯一标识一台主机上的服务
1.服务端处理流程:
 a.监听端口
b.接收客户端连接
c.处理该连接
2.客户端处理流程
a.建立与服务端的连接
b.进行数据收发
c.关闭连接
服务端:
package main
import(
	"fmt"
	"net"
)
func main(){
	fmt.Println("start server ...")
	lisen,err := net.Listen("tcp","0.0.0.0:8000")  //监听主机和端口 ip+port
	if err != nil {
		fmt.Println("listen failed,err:",err)
	}
	for {
		conn,err := lisen.Accept()   //conn 标识连接的每个客户端
		// fmt.Printf("第一次打印%#v",conn)               
		if err != nil {
			fmt.Println("accept failed ,err:",err)
			continue
		}
		go process(conn)         //调用 goroutine处理请求,否则的话只有这个连接关闭才能处理别的连接
	}
	
}
func process(conn net.Conn){
	defer conn.Close()
	// fmt.Printf("第二次打印#v",conn)
	for {                         //循环读取数据
		buf := make([]byte,512)
		_,err:= conn.Read(buf)   //把数据读取存储到buf中
		if err != nil {
			fmt.Println("read the data failed,err:",err)
			return
		}
		fmt.Println("read the string is",string(buf))
	}
}

  客户端:

package main
import(
	"fmt"
	"net"
	"bufio"
	"os"
	"strings"
)
func main(){
	conn, err := net.Dial("tcp","0.0.0.0:8000")    //连接服务器端
	if err != nil {
		fmt.Println("connection failed err:",err)
		return
	}
	defer conn.Close()
	inputReader := bufio.NewReader(os.Stdin)      
	for {
		input,_ := inputReader.ReadString('
')
		trimmedinput := strings.Trim(input,"
")
		if trimmedinput == "Q" {
			return
		}
		_,err = conn.Write([]byte(trimmedinput))      //写数据给服务端
		if err != nil {
			return
		}
	}

}

  上面实现了客户端向服务端发送数据,服务端读取数据,下面改一下,实现客户端与服务端的一个交互发送读取。

 服务端代码 :

package main
import(
	"fmt"
	"net"
	"bufio"
	"os"
	"strings"
)
func main(){
	fmt.Println("start server ...")
	lisen,err := net.Listen("tcp","0.0.0.0:8000")  //监听主机和端口 ip+port
	if err != nil {
		fmt.Println("listen failed,err:",err)
	}
	for {
		conn,err := lisen.Accept()   //conn 标识连接的每个客户端
		// fmt.Printf("第一次打印%#v",conn)               
		if err != nil {
			fmt.Println("accept failed ,err:",err)
			continue
		}
		go readprocess(conn)         //调用 goroutine处理请求,否则的话只有这个连接关闭才能处理别的连接
		go writeprocess(conn)
	}
	
}
func readprocess(conn net.Conn){
	defer conn.Close()
	// fmt.Printf("第二次打印#v",conn)
	for {                         //循环读取数据
		buf := make([]byte,512)
		_,err:= conn.Read(buf)   //把数据读取存储到buf中
		if err != nil {
			fmt.Println("read the data failed,err:",err)
			return
		}
		fmt.Println("from client:",string(buf))
		
	}
}
func writeprocess(conn net.Conn){
	defer conn.Close()
	fmt.Println("给客户端回复:")
	inputReader := bufio.NewReader(os.Stdin)      
	for {
		input,_ := inputReader.ReadString('
')
		trimmedinput := strings.Trim(input,"
")
		_,err := conn.Write([]byte(trimmedinput))      //写数据给客户端
		if err != nil {
			return
		}
	}
}

  客户端代码:

package main
import(
	"fmt"
	"net"
	"bufio"
	"os"
	"strings"
)
func main(){
	conn, err := net.Dial("tcp","0.0.0.0:8000")    //连接服务器端
	if err != nil {
		fmt.Println("connection failed err:",err)
		return
	}
	defer conn.Close()
	fmt.Println("给服务端回复:")
	inputReader := bufio.NewReader(os.Stdin)      
	for {
		input,_ := inputReader.ReadString('
')
		trimmedinput := strings.Trim(input,"
")
		if trimmedinput == "Q" {
			return
		}
		_,err = conn.Write([]byte(trimmedinput))      //写数据给服务端
		if err != nil {
			return
		}
		go readprocess(conn)
	}

}
func readprocess(conn net.Conn){
	defer conn.Close()
	for{
	buf := make([]byte,512)
	_,err:= conn.Read(buf)   //把数据读取存储到buf中
	if err != nil {
		fmt.Println("read the data failed,err:",err)
		return
	}
	fmt.Println("from server:",string(buf))
}
}

  

原文地址:https://www.cnblogs.com/wanghaijun999/p/8393340.html