• 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))
    }
    }
    

      

  • 相关阅读:
    sql语句开发使用---update
    获取弹出框的句柄,关闭弹出框
    水晶报表使用,解决相同数据库不同服务器使用同一个水晶报表模板问题?
    第一章 什么是SQL Server Integration Services (ssis) 系统。
    在 win 10 中使用sql 2012 附加低版本数据失败的解决办法。
    窗体间传值 委托应用
    有点小激动
    Adam
    SVN Unable to connect to a repository at URL问题解决
    C#基础---IComparable用法,实现List<T>.sort()排序
  • 原文地址:https://www.cnblogs.com/wanghaijun999/p/8393340.html
Copyright © 2020-2023  润新知