Go语言之进阶篇简单版并发服务器
1、简单版并发服务器
示例1:
package main import (
"fmt"
"net"
"strings"
) //处理用户请求
func HandleConn(conn net.Conn) {
//函数调用完毕,自动关闭conn
defer conn.Close() //获取客户端的网络地址信息
addr := conn.RemoteAddr().String()
fmt.Println(addr, " conncet sucessful") buf := make([]byte, 2048) for {
//读取用户数据
n, err := conn.Read(buf)
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Printf("[%s]: %s\n", addr, string(buf[:n]))
fmt.Println("len = ", len(string(buf[:n]))) //if "exit" == string(buf[:n-1]) { //nc测试
if "exit" == string(buf[:n-2]) { //自己写的客户端测试, 发送时,多了2个字符, "\r\n"
fmt.Println(addr, " exit")
return
} //把数据转换为大写,再给用户发送
conn.Write([]byte(strings.ToUpper(string(buf[:n]))))
} } func main() {
//监听
listener, err := net.Listen("tcp", "127.0.0.1:8000")
if err != nil {
fmt.Println("err = ", err)
return
} defer listener.Close() //接收多个用户
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("err = ", err)
return
} //处理用户请求, 新建一个协程
go HandleConn(conn)
} }
执行结果: 打开nc客户端:

2、简单版并发服务器
示例2:
tcp_server.go
package main import (
"fmt"
"net"
"strings"
) //处理用户请求
func HandleConn(conn net.Conn) {
//函数调用完毕,自动关闭conn
defer conn.Close() //获取客户端的网络地址信息
addr := conn.RemoteAddr().String()
fmt.Println(addr, " conncet sucessful") buf := make([]byte, 2048) for {
//读取用户数据
n, err := conn.Read(buf)
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Printf("[%s]: %s\n", addr, string(buf[:n]))
fmt.Println("len = ", len(string(buf[:n]))) //if "exit" == string(buf[:n-1]) { //nc测试
if "exit" == string(buf[:n-2]) { //自己写的客户端测试, 发送时,多了2个字符, "\r\n"
fmt.Println(addr, " exit")
return
} //把数据转换为大写,再给用户发送
conn.Write([]byte(strings.ToUpper(string(buf[:n]))))
} } func main() {
//监听
listener, err := net.Listen("tcp", "127.0.0.1:8000")
if err != nil {
fmt.Println("err = ", err)
return
} defer listener.Close() //接收多个用户
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("err = ", err)
return
} //处理用户请求, 新建一个协程
go HandleConn(conn)
} }
tcp_client.go
package main import (
"fmt"
"net"
"os"
) func main() {
//主动连接服务器
conn, err := net.Dial("tcp", "127.0.0.1:8000")
if err != nil {
fmt.Println("net.Dial err = ", err)
return
} //main调用完毕,关闭连接
defer conn.Close() go func() {
//从键盘输入内容,给服务器发送内容
str := make([]byte, 1024)
for {
n, err := os.Stdin.Read(str) //从键盘读取内容, 放在str
if err != nil {
fmt.Println("os.Stdin. err = ", err)
return
} //把输入的内容给服务器发送
conn.Write(str[:n])
}
}() //接收服务器回复的数据
//切片缓冲
buf := make([]byte, 1024)
for {
n, err := conn.Read(buf) //接收服务器的请求
if err != nil {
fmt.Println("conn.Read err = ", err)
return
}
fmt.Println(string(buf[:n])) //打印接收到的内容, 转换为字符串再打印
}
}
执行结果:

Go语言之进阶篇简单版并发服务器的更多相关文章
- go语言之进阶篇并行和并发的区别与go语言并发优势
1.并行和并发的概念 并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行. 并发(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在 ...
- go语言之进阶篇接口转换
1.go语音之进阶篇 示例: package main import "fmt" type Humaner interface { //子集 sayhi() } type Pers ...
- Linux:简单的并发服务器实现
我前两天实现了一个简单的服务器和一个对应的客户端,也简单的解决了一些错误检查和常用的函数的封装,但是那个服务器的一次只能连接一个客户端,鸡肋,太鸡肋了,今天我来实现可以连接多个客户端的服务器实例:多进 ...
- Go语言之进阶篇爬百度贴吧并发版
1.爬百度贴吧并发版 示例: package main import ( "fmt" "net/http" "os" "strco ...
- Go语言之进阶篇实现并发聊天功能
1.并发聊天服务器原理分析 2.并发聊天室 功能: 广播消息.广播上线. 查询在线用户.修改用户名.用户主动退出.超时处理 示例: package main import ( "fmt&qu ...
- go语言之进阶篇创建goroutine协程
1.goroutine是什么 goroutine是Go并行设计的核心.goroutine说到底其实就是协程,但是它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部帮你实现 ...
- go语言之进阶篇JSON处理
一.JSON处理 JSON (JavaScript Object Notation)是一种比XML更轻量级的数据交换格式,在易于人们阅读和编写的同时,也易于程序解析和生成.尽管JSON是JavaScr ...
- go语言之进阶篇正则表达式
正则表达式是一种进行模式匹配和文本操纵的复杂而又强大的工具.虽然正则表达式比纯粹的文本匹配效率低,但是它却更灵活.按照它的语法规则,随需构造出的匹配模式就能够从原始文本中筛选出几乎任何你想要得到的字符 ...
- C语言。自定义函数简单版
#include <stdio.h> //函数声明 void sayHi(); //函数实现 void sayHI() { printf("大家好!!\n"); } i ...
随机推荐
- Typecho-Material主题不支持Kotlin代码高亮的解决方案
Typecho-Material主题不支持Kotlin代码高亮的解决方案 Overview 最近通过Typecho搭建了一个Blog,采用了 Material主题,其他的都挺好,也挺喜欢这个主题,但是 ...
- Git的一些常用命令
一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 简单的说就是托管代码的便于多人开发的管理系统. 二.Git的一些命令,我详细的说一下 我是基于github给大家说一下git的一些常 ...
- jvm 参数配置优化
abtest业务线上接口每分钟执行3万多次,到半夜1点多访问量小的时候会经常报内存占比过高, 经调研分析发现与白天访问量高时线程数.cpu等无太大差异,主要差异存在内存会涨到很高并持续 一段时间. 现 ...
- 16、Redis手动创建集群
写在前面的话:读书破万卷,编码如有神 --------------------------------------------------------------------------------- ...
- JVM启动流程
JVM启动流程 (1)在java中jvm是通过java或javaw命令启动的,后面跟加载的类名. (2)jvm在启动的时候先根据[当前路径和系统版本寻找jvm的配置文件jvm.cfg]装载配置. (3 ...
- 使用 IntraWeb (26) - 基本控件之 TIWMenu
TIWMenu 的任务是让原来的 TMainMenu 呈现在网页上, 通过其 AttachedMenu 属性关联一个 TMainMenu 是必需的. TIWMenu 所在单元及继承链: IWCompM ...
- spring集成kafka
一.添加依赖项 compile 'org.springframework.kafka:spring-kafka:1.2.2.RELEASE' 二.发消息(生产者) 2.1 xml配置 <?xml ...
- C#实现路由器断开连接,更改公网ip
publicstaticvoid Disconnect() { string url ="断 线"; string uri ="http://192.168.1.1 ...
- 基于SmartThreadPool线程池技术实现多任务批量处理
一.多线程技术应用场景介绍 本期同样带给大家分享的是阿笨在实际工作中遇到的真实业务场景,请跟随阿笨的视角去如何采用基于开源组件SmartThreadPool线程池技术实现多任务批量处理.在工作中您是否 ...
- Delphi如何在Form的标题栏绘制自定义文字
Delphi中Form窗体的标题被设计成绘制在系统菜单的旁边,如果你想要在标题栏绘制自定义文本又不想改变Caption属性,你需要处理特定的Windows消息:WM_NCPAINT.. WM_NCPA ...