(46個)golang--ネットワークプログラミング(簡単なチャットシステム)

Goは、大規模なバックエンドサービス・プログラムの主な目的の一つであり、これは、ネットワーク通信サーバプログラムは、重要な部分に不可欠です。

ネットワークは、2つの方法でのプログラミング:

(1)TCPソケットプログラミング:底部がTCP / IPプロトコルに基づいているので、主流のネットワークプログラミング、TCPソケットプログラミングと呼ばれました。

(2)プログラミングHTTP B /サーバにアクセスするブラウザを使用する場合S構造、HTTPプロトコルが使用され、HTTP、TCPソケット底が達成されます。

コンピュータ間の通信必要は、ネットワークケーブル、ネットワークカードまたはワイヤレスネットワークカードを持っている必要があります。

TCP / IPモデル:アプリケーション層、トランスポート層、ネットワーク層、データリンク層、物理層、

 

IPアドレス:インターネット上のホストとルータはネットワーク番号とホスト番号を含むIPアドレスをそれぞれ有し、IPアドレスは、IPv4(32ビット)またはIPv6(128ビット)Ipconfigはを見ることができています。

ポート:ポート、ポートの論理的な意味で特にTCP / IPプロトコル。合計256×256-1 = 65535ポート。

ポートカテゴリー:

  • 0は、予約されたポートです。
  • 1〜1024であり、固定ポート(22:SSHリモートログインプロトコル、23:Telnetの使用、21:FTP使用、25:SMTPサービスの利用、80:LISは、7を使用:エコーサービス)
  • 1025から65535:プログラマが使用するダイナミックポート、;

サーバとクライアント間の通信のブロック図:

 

図から分かるように、それらの間の通信は、ポートによるものである(それは、単純な通信であるため、現在のクライアントのみクライアントを介して、直接通信しません)

server.go

package main

import (
    "fmt"
    "net"
)

func process(conn net.Conn) {
    //这里接受客户端的数据
    defer conn.Close()
    for {
        //创建一个新的切片
        buf := make([]byte, 1024)
        //等待客户端发送信息,如果客户端没发送,协程就阻塞在这
        // fmt.Printf("服务器在等待客户端%v的输入\n", conn.RemoteAddr().String())
        n, err := conn.Read(buf)
        if err != nil {
            // fmt.Println("服务器read err=", err)
            fmt.Println("客户端退出了")
            return
        }
        //显示客户端发送内容到服务器的终端
        fmt.Print(string(buf[:n]) + "\n")

    }
}

func main() {
    fmt.Println("服务器开始监听...")
    //协议、端口
    listen, err := net.Listen("tcp", "0.0.0.0:8888")
    if err != nil {
        fmt.Println("监听失败,err=", err)
        return
    }
    //延时关闭
    defer listen.Close()
    for {
        //循环等待客户端连接
        fmt.Println("等待客户端连接...")
        conn, err := listen.Accept()
        if err != nil {
            fmt.Println("Accept() err=", err)
        } else {
            fmt.Printf("Accept() suc con=%v,客户端Ip=%v\n", conn, conn.RemoteAddr().String())
        }
        //这里准备起个协程为客户端服务
        go process(conn)
    }
    //fmt.Printf("监听成功,suv=%v\n", listen)
}

client.go

package main

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

func main() {
    //同样是tcp协议,192.168.1.145服务端的ip地址,这里是我自己本机的地址,可在终端用ipconfig查看,后面是服务端开启的端口号
    conn, err := net.Dial("tcp", "192.168.1.145:8888")
    if err != nil {
        fmt.Println("client dial err=", err)
        return
    }
    //哭护短在命令行输入单行数据
    reader := bufio.NewReader(os.Stdin)
    for {
        //从终端读取一行用户的输入,并发给服务器
        line, err := reader.ReadString('\n')
        if err != nil {
            fmt.Println("readString err=", err)
        }
        //去掉输入后的换行符
        line = strings.Trim(line, "\r\n")
        //如果是exit,则退出客户端
        if line == "exit" {
            fmt.Println("客户端退出了")
            break
        }
        //将line发送给服务器
        _, e := conn.Write([]byte(line))
        if e != nil {
            fmt.Println("conn.write err=", e)
        }
        // fmt.Printf("客户端发送了%d字节的数据,并退出", n)
    }
}

首先在一个终端打开服务器:

然后连接两个客户端:

注意到,每个客户端的端口号是不一致的:

然后两个客户端分别发送消息给服务端:

服务端可以接收到信息:

 最后输入exit分别关闭两个客户端:

两个客户端都退出了,然后服务端继续等待新的客户端的连接。 

おすすめ

転載: www.cnblogs.com/xiximayou/p/11966620.html