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. oracle merge同时包含增、删、改

    原来一直没注意,merge是可以支持delete,只不过必须的是on条件满足,也就是要求系统支持逻辑删除,而非物理删除. Using the DELETE Clause with MERGE Stat ...

  2. UML建模类图【2】--☆☆

    虚线箭头指向依赖: 实线箭头指向关联: 虚线三角指向接口: 实线三角指向父类: 空心菱形能分离而独立存在,是聚合: 实心菱形精密关联不可分,是组合: 上面是UML的语法. 在画类图的时候,理清类和类之 ...

  3. bzoj 4585 烟火表演 - 动态规划 - 可并堆

    题目传送门 传送门I 传送门II 题目大意 给定一棵带边权有根树,修改一条边的边权的代价是修改前和修改后的值的绝对值之差.不能将一条边的边权改为负数.问使得根节点到所有叶节点的距离相等的最小代价. 当 ...

  4. Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) Problem A - B

    Pronlem A In a small restaurant there are a tables for one person and b tables for two persons. It i ...

  5. C++进程间通信之共享内存

    转载:http://blog.csdn.net/taily_duan/article/details/51692999 转载:http://blog.csdn.net/fengrx/article/d ...

  6. spring动态创建数据源

    在最近的项目业务中,需要在程序的运行过程中,添加新的数据库添链接进来,然后从新数据库链接中读取数据. 网上查阅了资料,发现spring为多数据源提供了一个抽象类AbstractRoutingDataS ...

  7. Flask学习【第7篇】:Flask中的wtforms使用

    简介flask中的wtforms WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证. 安装 pip3 install wtforms 简单使用wtforms组件 用 ...

  8. linux内核中的DMI是什么?

    答: 桌面管理接口(Desktop Management Interface).是用来获取硬件信息的,在内核中有一个配置项CONFIG_DMI用来添加此功能到内核中!

  9. 【BZOJ2724】【Violet 6】蒲公英

    蒲公英/分块入门九Byhzwer 辣鸡我复制粘贴题面格式极其丑陋,各位看原题面啦. [题目描述] 在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关. 为了简化起见,我们把所有的蒲公英看成 ...

  10. 2870: 最长道路tree

    链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2870 思路 先把树转化为二叉树 再链分治 %%yyb 代码 #include <ios ...