Ir núcleo notas de estudio de desarrollo (treinta) - / IP, la programación de red TCP

conocimiento de TCP / IP saltado más o menos un resumen de los puntos

  1. Apreciará que la OSI de siete capas teoría de modelos, se entenderá que el modelo de estructura de cuatro capas TCP / IP: la capa de aplicación, capa de transporte, capa de red, capa de interfaz de red.
  2. protocolo TCP / IP contiene una gran cantidad de protocolos, TCP e IP son sólo dos entre los más representativos.
  3. estructura C / S: los representantes de mensajería instantánea pertenecen a la programación del zócalo TCP; B / S estructura: Representante centro comercial JD, programa perteneciente a HTTP, TCP es parte de protocolo HTTP / IP.
  4. Acerca de la sección de red, debe ser un profundo conocimiento de TCP / IP, con el fin de un mejor seguimiento del desarrollo, el Departamento no repetirlos.
  5. Puerto menos abierta, para abrir más de una copia del riesgo, el servidor puede abrir puertos cada vez menos abierta, el sistema debe ser de la versión pura, de un solo puerto que corresponde a un solo programa, no se puede reutilizar;

TCP enchufe de programación del lado del cliente y del lado del servidor

  1. Multi-Client corresponden generalmente Servidor minoría.
  2. El flujo de procesamiento del servidor:
    puerto de escucha (Listening);
    recepción de solicitudes TCP cliente para establecer cliente y del lado del servidor de enlace;
    crear goroutine, el procesamiento de la petición de enlace (Cliente mediante el envío de un paquete de petición).
  3. Cliente Flujo de proceso:
    el establecimiento del enlace y el lado de servicio (escucha en el puerto ligado servidor de puerto-aleatoria definida);
    los datos de solicitud de envío, el servidor de recepción devuelve los resultados de los datos;
    estrechos vínculos (TCP que representa el consumo de recursos, similar a abrir el archivo que desee aplazar el apagado para evitar la memoria fuga);

la práctica real, el cliente y servidor para escribir un modelo C / S para transmitir y recibir información, un terminal de entrada, un terminal de salida

El análisis del lado del servidor y comentarios:

package main

import (
	"fmt"
	"net"
)

func recv(conn net.Conn) {
	//循环接收客户端发送来的请求
	defer conn.Close()    //如果不关闭服务器因为连接没有释放,后续客户端无法登陆了
	for {
		//创建一个新的切片
		buf := make([]byte,1024)
		//fmt.Printf("服务器在等待客户端%v发送信息\n",conn.RemoteAddr().String())
		n, err := conn.Read(buf)  //如果客户端conn不发信息,没有write操作,会一直阻塞,优化做一个timeout
		if err != nil {
			return
		}
		//显示信息到服务器终端,buf[:n]是真正读到的信息,否则切片后一大串东西都会出来,很乱套
		fmt.Print(string(buf[:n]))
	}
}

func main() {
	/*
	需求分析:
	1. 服务端: 监听端口6666,要为多个客户端提供服务;
	   不能阻塞,所以每个客户端请求都用一个goroutine提供服务;
		MPG模型,P调度处一个goroutine为客户端x提供服务,实际上是不同的G在为不同的client提供服务;
		全部开协程,就变成了并发的了,同时进行请求响应。
	2. 客户端: 端口随机,通过Socket发送请求指定到服务器端6666端口
	 */

	/*
	服务器端代码编写: package net中
	大部分使用者只需要Dial、Listen和Accept函数提供的基本接口,以及相关的Conn和Listener接口。
	crypto/tls包提供了相同的接口和类似的Dial和Listen函数。

	Dial函数和服务端建立连接,Listen函数创建的服务端。
	 */
	listener, err := net.Listen("tcp", "0.0.0.0:6666")   //返回listener为接口类型资源
	if err != nil {
		fmt.Println("连接错误,程序退出")  //监听都错误,后面不用玩了
		return
	}
	defer listener.Close()   //类似文件,及时关闭
	//监听成功,获得ln为&{0xc00008e000}
	fmt.Printf("监听成功,获得lnr为%v\n",listener) //相当于监听成功就跑路了,所以需要for循环。
	for {
		//关于conn接口类型资源拥有的方法:
		/*
		// Read从连接中读取数据
		   // Read方法可能会在超过某个固定时间限制后超时返回错误,该错误的Timeout()方法返回真
		   Read(b []byte) (n int, err error)
		   // Write从连接中写入数据
		   // Write方法可能会在超过某个固定时间限制后超时返回错误,该错误的Timeout()方法返回真
		   Write(b []byte) (n int, err error)
		   // Close方法关闭该连接
		   // 并会导致任何阻塞中的Read或Write方法不再阻塞并返回错误
		   Close() error
		   // 返回本地网络地址
		   LocalAddr() Addr
		   // 返回远端网络地址
		   RemoteAddr() Addr
		 */
		conn, err := listener.Accept()  // Accept等待并返回下一个连接到该接口的连接, conn为接口类型实例,通俗点,通信连接线对象
		if err != nil {
			continue    //这里出错了不要使用return或者break,因为并发连接千万,不能因为一个就终止服务器监听
		} else {
			fmt.Printf("Accept() successed conn = %v\n",conn)
			fmt.Printf("客户端IP= %v\n",conn.RemoteAddr().String())   // 返回远端网络地址

		}
		
		//起一个协程为连接进来的客户端提供一对一服务,监听是通过服务器主程序
		// 端口仍然是同一个,类似前台,但是提供读写等,为客户端服务的是协程
		go recv(conn)
	}
}

Cliente Cliente y anotación análisis:

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
	"strings"
)

func main() {
	//客户端使用net.Dial()来完成,无需要监听,只需要conn即可
	conn, err := net.Dial("tcp","127.0.0.1:6666")
	if err != nil {
		fmt.Println("连接错误,错误原因为:",err,"请重新连接")
		return
	} else {
		fmt.Println("conn is successfully connect~",conn)
	}

	reader := bufio.NewReader(os.Stdin)

	for {
		ln, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("Reading String Error!")
		}


		ln = strings.Trim(ln,"\r\n")
		if ln == "exit" {
			fmt.Println("客户端由于exit命令退出")
			break
		}

		_, err = conn.Write([]byte(ln + "\n"))
		if err != nil {
			fmt.Println("Writing error!",err)
		}
	}
}
Publicado 49 artículos originales · alabanza ganado 18 · vistas 3995

Supongo que te gusta

Origin blog.csdn.net/weixin_41047549/article/details/90677920
Recomendado
Clasificación