1.本例子实现了一个简单的TCP echo。客户端发送Hello,服务端回应World。

参考:《Socket编程》

2.服务端代码

package main

import (
"net"
"fmt"
"os"
"time"
) //错误处理函数
func checkErr(err error, extra string) bool {
if err != nil {
formatStr := " Err : %s\n";
if extra != "" {
formatStr = extra + formatStr;
} fmt.Fprintf(os.Stderr, formatStr, err.Error());
return true;
} return false;
} //连接处理函数
func svrConnHandler(conn net.Conn) {
fmt.Println("Client connect success :", conn.RemoteAddr().String());
conn.SetReadDeadline(time.Now().Add( * time.Minute))
request := make([]byte, );
defer conn.Close();
for {
readLen, err := conn.Read(request)
if checkErr(err, "Read") {
break;
} //socket被关闭了
if readLen == {
fmt.Println("Client connection close!");
break;
} else {
//输出接收到的信息
fmt.Println(string(request[:readLen])) time.Sleep(time.Second);
//发送
conn.Write([]byte("World !"));
} request = make([]byte, );
}
} func main() {
//解析地址
tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:6666");
if checkErr(err, "ResolveTCPAddr") {
return;
} //设置监听地址
listener, err := net.ListenTCP("tcp", tcpAddr);
if checkErr(err, "ListenTCP") {
return;
} for {
//监听
fmt.Println("Start wait for client.")
conn, err := listener.Accept();
if checkErr(err, "Accept") {
continue;
} //消息处理函数
go svrConnHandler(conn);
}
}

3.客户端代码

package main

import (
"fmt"
"os"
"net"
"sync"
) var gLocker sync.Mutex; //全局锁
var gCondition *sync.Cond; //全局条件变量 //错误处理函数
func checkErr(err error, extra string) bool {
if err != nil {
formatStr := " Err : %s\n";
if extra != "" {
formatStr = extra + formatStr;
} fmt.Fprintf(os.Stderr, formatStr, err.Error());
return true;
} return false;
} //连接处理函数
func clientConnHandler(conn net.Conn) {
gLocker.Lock();
defer gLocker.Unlock(); defer conn.Close(); request := make([]byte, );
for {
readLen, err := conn.Read(request)
if checkErr(err, "Read") {
gCondition.Signal();
break;
} //socket被关闭了
if readLen == {
fmt.Println("Server connection close!"); //条件变量同步通知
gCondition.Signal();
break;
} else {
//输出接收到的信息
fmt.Println(string(request[:readLen])) //发送
conn.Write([]byte("Hello !"));
} request = make([]byte, );
}
} func main() {
//解析地址
tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:6666");
if checkErr(err, "ResolveTCPAddr") {
return;
} conn, err := net.DialTCP("tcp", nil, tcpAddr);
if checkErr(err, "DialTCP") {
return;
} fmt.Println("Connect server success.") gLocker.Lock();
gCondition = sync.NewCond(&gLocker); //发送数据给服务器
conn.Write([]byte("Hello !")); //处理连接(lock在上面调用了,所以clientConnHandler函数必须等wait函数调用后才能lock,这样就能保证调用的先后顺序)
go clientConnHandler(conn); //主线程阻塞,等待Singal结束
for {
//条件变量同步等待
gCondition.Wait();
break;
}
gLocker.Unlock();
fmt.Println("Client finish.")
}

PS:关于sync.Cond可以参考下一篇文章:《Golang sync》

4.结果截图

以上。

Golang socket的更多相关文章

  1. golang socket 分析

    socket:tcp/udp.ip构成了网络通信的基石,tcp/ip是面向连接的通信协议 要求建立连接时进行3次握手确保连接已被建立,关闭连接时需要4次通信来保证客户端和,服务端都已经关闭 在通信过程 ...

  2. golang socket 实现分析(一)

    socket:tcp/udp.ip构成了网络通信的基石,tcp/ip是面向连接的通信协议 要求建立连接时进行3次握手确保连接已被建立,关闭连接时需要4次通信来保证客户端和,服务端都已经关闭 在通信过程 ...

  3. golang socket与Linux socket比较分析

    在posix标准推出后,socket在各大主流OS平台上都得到了很好的支持.而Golang是自带runtime的跨平台编程语言,Go中提供给开发者的socket API是建立在操作系统原生socket ...

  4. Linux下Golang Socket编程原理分析与代码实现

    在POSIX标准推出后,socket在各大主流OS平台上都得到了很好的支持.而Golang是自带Runtime的跨平台编程语言,Go中提供给开发者的Socket API是建立在操作系统原生Socket ...

  5. [转] golang socket

    server.go package main import ( "net" "fmt" "io/ioutil" "time&quo ...

  6. Golang Socket编程

    Socket编程 在很多底层网络应用开发者的眼里一切编程都是Socket,话虽然有点夸张,但却也几乎如此了,现在的网络编程几乎都是用Socket来编程.你想过这些情景么?我们每天打开浏览器浏览网页时, ...

  7. golang socket编程 net.Conn IO.EOF解读

    结论 首先,先定义下我的理解,当在Read时,收到一个IO.EOF,代表的就是对端已经关闭了发送的通道,通常来说是发起了FIN. 那么根据自己的实际业务,就可以进行判断,这里的IO.EOF到底该怎么利 ...

  8. Golang websocket

    环境:Win10 + Go1.9.2 1.先下载并引用golang的websocket库 ①golang的官方库都在https://github.com/golang下,而websocket库在/ne ...

  9. Golang开发支持平滑升级(优雅重启)的HTTP服务

    Golang开发支持平滑升级(优雅重启)的HTTP服务 - tabalt的博客 http://tabalt.net/blog/graceful-http-server-for-golang/ http ...

随机推荐

  1. Java线程安全容器

    一.Java同步容器 同步容器是用来解决并发情况下的容器线程安全问题的.给多线程环境准备一个线程安全的容器对象. 线程安全的容器对象: Vector, Hashtable.线程安全容器对象,都是使用s ...

  2. k8s开发环境

    在搭建开发环境之前, 请Try Kubernetes,Get Started and CONCEPTS 可以自己使用minikube 来搭建个环境, 自己玩一玩. K8s需要一些依赖. 参看官方文档 ...

  3. 快速阅读《QT5.9 c++开发指南》1

    简介:<QT5.9 c++开发指南>的作者是和i三位主要从事地球物理探测仪器设计.数据处理方法研究和软件开发等工作的博士们,这本书以QT Widget为主要内容,比较全面地教授了QT开发桌 ...

  4. Stanford CS231n实践笔记(课时14卷积神经网络详解 上)

    本课我们主要来研究一个"浏览器中的卷积神经网络" 这只是一个展示项目,但是能够帮助直观地看到一些东西 地址:https://cs.stanford.edu/people/karpa ...

  5. 【python011--数组2】

    一.从列表中获取元素 *跟数组一样,我们可以通过元素的索引值(index)从列表获取单个元素,注意,列表索引值是从0开始的 >>> member= ['尘封','冰点','无名',' ...

  6. SVM学习笔记4-核函数和离群点的处理

    核函数在svm里,核函数是这样定义的.核函数是一个n*n(样本个数)的矩阵,其中:$K_{ij}=exp(-\frac{||x^{(i)}-x^{(j)}||^{2}}{2\sigma ^{2}})$ ...

  7. uniGUI试用笔记(六)

    uniGUI提供了一个文件上传控件TUniFileUpload,进行数据的导入就变得比较容易.首先将TUniFileUpload控件放置在窗体上,按下导入按钮后,执行TUniFileUpload的文件 ...

  8. 如何生成指定架构的Linux内核默认配置文件

    答: make ARCH=<cpu architecture> defconfig 举例如下: make ARCH=arm64 defconfig (编译系统将会去目录arch/arm64 ...

  9. linux下gzip的压缩详解

    Linux压缩保留源文件的方法: gzip -c filename > filename.gz Linux解压缩保留源文件的方法: gunzip -c filename.gz > file ...

  10. Entity Framework Core导航属性加载问题

    前言 今天下午在开发的时候发现EF Core实体模型中的导航属性为 null,经排查既不是没有加 virtual 关键字,也不是外键关系映射错误. 解决方法 通过查询官网文档,发现,原因在于EF Co ...