zoukankan      html  css  js  c++  java
  • 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))
    }
    }
    

      

  • 相关阅读:
    Please check logcat output for more details
    如何移植freertos
    依赖: nginx-common (= 1.14.0-0ubuntu1) 但是它将不会被安装
    错误:22 http://ppa.launchpad.net/fkrull/deadsnakes/ubuntu bionic Release 404 Not Found [IP: 91.189.95.83 80]
    由于没有公钥,无法验证下列签名:
    jQuery的TAB切换+定时器
    CSS问题1:div中 li宽度不固定 ie6和ie7不兼容不自动换行
    (转)Sqlite中INTEGER PRIMARY KEY AUTOINCREMENT和rowid的使用
    (转)JS加载顺序
    (转)在网页中JS函数自动执行常用三种方法
  • 原文地址:https://www.cnblogs.com/wanghaijun999/p/8393340.html
Copyright © 2011-2022 走看看