Go主要的目标之一就是面向大规模后端服务程序,网络通信这块是服务端程序必不可少也是至关键的一部分。

网络编程有两种:

(1)TCP Socket编程:是网络编程的主流,之所以叫TCP Socket编程,是因为底层是基于TCP/IP协议的;

(2)B/S结构的http编程,使用浏览器去访问服务器时,使用的就是http协议,而http底层就是tcp socket实现的;

计算机间需要通讯,必须要有网线、网卡或者是无线网卡;

TCP/IP模型:应用层、传输层、网络层、数据链路层、物理层;

IP地址:每个internet上的主机和路由器都有一个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:echo服务)
  • 1025-65535:是动态端口,供程序员使用;

服务端和客户端之间通信框图:

可以看出,它们之间的通信是通过端口 (由于是简易的通讯,目前客户端并不能直接交流,只能通过客户端)

server.go

package main

import (
"fmt"
"net"
) func process(conn net.Conn) {
//这里接受客户端的数据
defer conn.Close()
for {
//创建一个新的切片
buf := make([]byte, )
//等待客户端发送信息,如果客户端没发送,协程就阻塞在这
// 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分别关闭两个客户端:

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

(四十六)golang--网络编程(简易的聊天系统)的更多相关文章

  1. Python学习笔记(四十六)网络编程(2)— UDP编程

    摘抄:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014320049779 ...

  2. Python学习笔记(四十五)网络编程(1)TCP编程

    摘抄:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014320043745 ...

  3. Android简易实战教程--第四十六话《RecyclerView竖向和横向滚动》

    Android5.X后,引入了RecyclerView,这个控件使用起来非常的方便,不但可以完成listView的效果,而且还可以实现ListView无法实现的效果.当然,在新能方便也做了大大的提高. ...

  4. JAVA第十周《网络编程》学习内容总结

    JAVA第十周<网络编程>学习内容总结 学习内容总结 1.初听到网络编程四个字可能会觉得很困难,实际上网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据,把数据发送到指定的位置, ...

  5. NeHe OpenGL教程 第四十六课:全屏反走样

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  6. 四十六、android中的Bitmap

    四十六.android中的Bitmap: http://www.cnblogs.com/linjiqin/archive/2011/12/28/2304940.html 四十七.实现调用Android ...

  7. python---基础知识回顾(六)网络编程2(处理粘包)

    前戏: 之前在python---基础知识回顾(六)网络编程异步模块中提到过粘包现象,而且在使用twisted中提到过一种处理办法,按行接收lineReceived,当收到\r\n换行符时,才去缓冲区中 ...

  8. “全栈2019”Java第四十六章:继承与字段

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  9. golang 网络编程之如何正确关闭tcp连接以及管理它的生命周期

    欢迎访问我的个人网站获取更佳阅读排版 golang 网络编程之如何正确关闭tcp连接以及管理它的生命周期 | yoko blog (https://pengrl.com/p/47401/) 本篇文章部 ...

  10. 第四十六个知识点 在Sigma协议中,正确性,公正性和零知识性意味着什么

    第四十六个知识点 在Sigma协议中,正确性,公正性和零知识性意味着什么 Sigma协议 Sigma协议是Alice想要向Bob证明一些东西的协议(Alice知道一些秘密).他们有下面的一般范式:Al ...

随机推荐

  1. SpringBoot系列之YAML配置用法

    1.全局配置 SpringBoot的全局配置文件有两种: application.properties application.yml 配置文件的作用:修改SpringBoot自动配置的默认值,主要是 ...

  2. SpringBoot配置文件之Yml语法

    一 使用 YAML 而不是 Properties YAML是 JSON 的超集,因此,它是用于指定分层配置数据的便捷格式.只要 class 路径上有SnakeYAML library,SpringAp ...

  3. SpringBoot与MybatisPlus3.X整合之通用枚举(十二)

    一 通用枚举 解决了繁琐的配置,让 mybatis 优雅的使用枚举属性! 自3.1.0开始,可配置默认枚举处理类来省略扫描通用枚举配置 默认枚举配置 升级说明: 3.1.0 以下版本改变了原生默认行为 ...

  4. 牛客练习赛51 **E-数列** (二分,贪心,构造)

    牛客练习赛51 E-数列 链接:https://ac.nowcoder.com/acm/contest/1083/E来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 327 ...

  5. 简要概括java技术体系

    以前一直在学java程序设计语言,学完了就以为自己已经把java学得差不多了,直到最近在看一本书<深入理解java虚拟机>,才发现自己以前学的只不过是冰山一角.相信很多小伙伴跟我一样,在没 ...

  6. 在虚拟机上的关于Apache(阿帕奇)(2)开启个人用户主页功能

    首先下载httpd服务 在这里我们主要谈一谈个人主页功能分为不加密和加密两种 不加密 我们先来建立几个用户,使用命令:useradd  longshisan 使用命令:   Passwd  longs ...

  7. 智和网管平台SugarNMS助力网络安全运维等保2.0建设

    智和信通智和网管平台SugarNMS结合<信息安全技术 网络安全等级保护基本要求>(GB/T 22239-2019)等国家标准文件以及用户提出的网络安全管理需求进行产品设计,推出“监控+展 ...

  8. python学习之【第六篇】:Python中的字典及其所具有的方法

    1.前言 字典是python中唯一的映射类型,采用键值对(key-value)的形式存储数据.python对key进行哈希函数运算,根据计算的结果决定value的存储地址,因此,字典的key必须是可哈 ...

  9. 主席树学习笔记(静态区间第k大)

    题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出 ...

  10. Eclipse SVN插件的帐号、密码修改

    Eclipse的SVN插件Subclipse做得很好,在svn操作方面提供了很强大丰富的功能.但到目前为止,该插件对svn用户的概念极为淡薄,不但不能方便地切换用户,而且一旦用户的帐号.密码保存之后, ...