Go292:socket-client--server 从单次连接到多次连接

网络分层

OSI七层网络模型TCP/IP四层概念模型对应网络协议 |
应用层 (Application)应用层HTTP、TFTP、FTP、NFS、WAIS、SMTP
表示层(Presentation)Telnet、Rlogin、SNMP、Gopher
会话层 (Session)SMTP、DNS
传输层 (Transport)传输层TCP、UDP
网络层 (Network)网络层IP、ICMP、ARP、RARP、AKP、UUCP
数据链路层 (Data link)数据链路层FDDI、Ethernet、Arpanet、PDN、SLIP、PPP
物理层 (Physical)IEEE 802.1A、IEEE 802.2到IEEE 802.11

socket-client–server通信过程分析

请添加图片描述

socket-server-单次处理

server DEMO

接收一个链接,而且只能发送一次数据
请添加图片描述

package main

import (
	"fmt"
	"net"
	"strings"
)

func main() {
	//创建监听
	ip := "127.0.0.1"
	port := 8849
	address := fmt.Sprintf("%s:%d", ip,port)

	//func Listen(network string, address string) (Listener, error)
	listener,err := net.Listen("tcp",address)
	//net.Listen("tcp",":8848")//简写,冒号前面默认是本机localhost:127.0.0.1

	if err != nil {
		fmt.Println("net.Listen err :", err)
		return
	}

	fmt.Println("监听中...")
	//func (Listener) Accept() (Conn, error)
	conn,err := listener.Accept()
	if err != nil {
		fmt.Println("listener.Accpet err:",err)
		return
	}

	fmt.Println("链接建立成功")

	//创建一个容器,用于j接收读取到的数据
	buf := make([]byte,1024)//使用make来创建切片,byte==> uint8

	//Read(b []byte) (n int, err error)
	//cnt:真正读取client发来的数据的长度,因为用户具体发了多少不知道
	cnt, err := conn.Read(buf)
	if err != nil {
		fmt.Println("conn.Read err:",err)
		return
	}

	fmt.Println("Client ======> server ,长度:", cnt,",数据", string(buf[:cnt]))

	//server对client请求进行响应,将数据转换成大写"hello"==>HELLO

	//将数据转成大写"hello"==> HELLO
	//func ToUpper(s string) string
	upperData := strings.ToUpper(string(buf[:cnt]))
	//Write(b []byte) (n int, err error)
	cnt, err = conn.Write([]byte(upperData))
	fmt.Println("Client<=======server ,长度",cnt,",数据:",upperData)

	//关闭这个链接
	conn.Close()

}

运行结果

tianyi@SPACE-STATION day1 % go run socket-serverdomo.go 
监听中...
链接建立成功
Client ======> server ,长度: 10 ,数据 helloworld
Client<=======server ,长度 10 ,数据: HELLOWORLD

```

## client DEMO
````go
package main

import (
	"fmt"
	"net"
)

func main() {
	//func Dial(network, address string) (Conn, error) {
	conn, err := net.Dial("tcp",":8849")
	if err != nil {
		fmt.Println("net.Dial err:", err)
		return
	}

	fmt.Println("client与server链接建立成功!")

	sendData := []byte("helloworld")
	//向服务器发送数据
	cnt, err := conn.Write(sendData)
	if err != nil {
		fmt.Println("conn.Write err:", err)
		return
	}


	fmt.Println("Client====>server cnt:",cnt,",data:",string(sendData))
	//接受服务器返回的数据
	//创建buf用于接受server返回的数据
	buf := make([]byte,1024)
	cnt, err = conn.Read(buf)
	if err != nil {
		fmt.Println("conn.Read err:", err)
		return
	}

	fmt.Println("Client<=====server,cnt:", cnt,",data", string(buf[:cnt]))

	conn.Close()
}

运行结果

tianyi@SPACE-STATION day1 % go run socket-clientdome.go
client与server链接建立成功!
Client====>server cnt: 10 ,data: helloworld
Client<=====server,cnt: 10 ,data HELLOWORLD

socket-client-server 处理多个链接,每个连接可以接收多次数据

server端 主进程用来监听,业务由单独的go func启动

package main

import (
	"fmt"
	"net"
	"strings"
)

func main() {
	//创建监听
	ip := "127.0.0.1"
	port := 8849
	address := fmt.Sprintf("%s:%d", ip, port)//通过fmt.Sprintf()将ip:port拼成字符串

	//func Listen(network string, address string) (Listener, error)
	listener, err := net.Listen("tcp", address)
	//net.Listen("tcp",":8848")//简写,冒号前面默认是本机localhost:127.0.0.1

	if err != nil {
		fmt.Println("net.Listen err :", err)
		return
	}

	//需求:
	//server可以接收多个连接,====> 主go程负责监听,子go程负责数据处理
	//每个链接可以接收处理多轮数据请求

	for {
		fmt.Println("监听中...")

		//主进程只负责建立连接
		//func (Listener) Accept() (Conn, error)
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("listener.Accpet err:", err)
			return
		}

		fmt.Println("链接建立成功")

		go handleFunc(conn)

	}
}

//处理具体业务的逻辑,需要将conn传递过来,每一个新的链接,conn是彼此独立的
func handleFunc(conn net.Conn) {
	for {//这个for循环,可以保证每一个连接可以多次接受处理客户端请求

		//创建一个容器, 用于j接收读取到的数据
		buf := make([]byte, 1024) //使用make来创建切片,byte==> uint8

		fmt.Println("准备读取客户端发送的数据......")

		//Read(b []byte) (n int, err error)
		//cnt:真正读取client发来的数据的长度,因为用户具体发了多少不知道
		cnt, err := conn.Read(buf)
		if err != nil {
			fmt.Println("conn.Read err:", err)
			return
		}

		fmt.Println("Client ======> server ,长度:", cnt, ",数据", string(buf[:cnt]))
		//server对client请求进行响应,将数据转换成大写"hello"==>HELLO

		//将数据转成大写"hello"==> HELLO
		//func ToUpper(s string) string
		upperData := strings.ToUpper(string(buf[:cnt]))
		//Write(b []byte) (n int, err error)
		cnt, err = conn.Write([]byte(upperData))
		fmt.Println("Client<=======server ,长度", cnt, ",数据:", upperData)

		//关闭这个链接  下划线代表忽略这个值,用来接受err
	}
	_ = conn.Close()
}

client端

package main

import (
	"fmt"
	"net"
	"time"
)

func main() {
	//func Dial(network, address string) (Conn, error) {
	conn, err := net.Dial("tcp", ":8849")
	if err != nil {
		fmt.Println("net.Dial err:", err)
		return
	}

	fmt.Println("client与server链接建立成功!")

	sendData := []byte("helloworld")

	for {
		//向服务器发送数据
		cnt, err := conn.Write(sendData)
		if err != nil {
			fmt.Println("conn.Write err:", err)
			return
		}

		fmt.Println("Client====>server cnt:", cnt, ",data:", string(sendData))
		//接受服务器返回的数据
		//创建buf用于接受server返回的数据
		buf := make([]byte, 1024)
		cnt, err = conn.Read(buf)
		if err != nil {
			fmt.Println("conn.Read err:", err)
			return
		}

		fmt.Println("Client<=====server,cnt:", cnt, ",data", string(buf[:cnt]))
		time.Sleep(1*time.Second)
	}

	conn.Close()
}

terminal
1、client

tianyi@SPACE-STATION day1 % go run socket-clientdome.go
client与server链接建立成功!
Client====>server cnt: 10 ,data: helloworld
Client<=====server,cnt: 10 ,data HELLOWORLD
tianyi@SPACE-STATION day1 % go run socket-clientdome.go
client与server链接建立成功!
Client====>server cnt: 10 ,data: helloworld
Client<=====server,cnt: 10 ,data HELLOWORLD

2、server

tianyi@SPACE-STATION day1 % go run socket-server-多链接.go
监听中...
链接建立成功
监听中...
准备读取客户端发送的数据......
Client ======> server ,长度: 10 ,数据 helloworld
Client<=======server ,长度 10 ,数据: HELLOWORLD
准备读取客户端发送的数据......
conn.Read err: EOF
链接建立成功
监听中...
准备读取客户端发送的数据......
Client ======> server ,长度: 10 ,数据 helloworld
Client<=======server ,长度 10 ,数据: HELLOWORLD
准备读取客户端发送的数据......
conn.Read err: EOF

当client多次发送数据时
请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值