socket编程
cs架构-socket编程.jpg服务器编码---多协程和服务器通信
// 服务器代码
package main
import (
"fmt"
"io"
"log"
"net"
"runtime"
"strings"
)
func main() {
listener, err := net.Listen("tcp", "10.0.154.199:8899")
if err != nil {
return
}
defer listener.Close()
// 循环等待客户端接入
for {
conn, err := listener.Accept() // 阻塞等待客户端接入
if err != nil {
continue
}
go handle(conn) // 将连接传入执行 函数
}
}
func handle(conn net.Conn) {
defer conn.Close() // 执行完关闭资源
defer fmt.Println(conn.RemoteAddr(), "已经退出连接") // 执行完关闭资源
fmt.Println(conn.RemoteAddr(), "已经连接") // 10.0.154.199:11307 已经连接
buf := make([]byte, 1024) // 创建一个byte的切片容器
for {
n, err1 := conn.Read(buf) // n为读到的内容长度
if err1 != nil && err1 != io.EOF {
fmt.Println("xxxxxxxxxxxxx")
log.Print(err1)
return
}
str := string(buf[:n])
if str == "exit" {
fmt.Println("------------------")
runtime.Goexit()
} else {
str = strings.ToUpper(str)
}
conn.Write([]byte(str))
}
}
// 客户端代码
func main() {
conn, err := net.Dial("tcp", "10.0.154.199:8899")
defer conn.Close()
if err != nil {
return
}
dealWith(conn)
}
func dealWith(conn net.Conn) {
buf := make([]byte, 1024)
for {
fmt.Scan(&buf)
conn.Write(buf)
n, err1 := conn.Read(buf)
if err1 != nil {
return
}
fmt.Printf("服务器返回:%s\n", string(buf[:n]))
}
}
文件传输程序
接收方代码:
package main
import (
"fmt"
"io"
"net"
"os"
)
func main() {
listener, err := net.Listen("tcp", "10.0.154.199:8899")
defer listener.Close()
if err != nil {
return
}
conn, err1 := listener.Accept()
defer conn.Close()
if err1 != nil {
return
}
// 接收文件名
fileBuf := make([]byte, 1024)
n, err2 := conn.Read(fileBuf)
if err2 != nil {
return
}
fileName := string(fileBuf[:n])
fmt.Println(fileName)
// 回复ok
conn.Write([]byte("ok"))
// 接收文件内容
receiveFile(fileName, conn)
}
func receiveFile(fileName string, conn net.Conn) {
buf := make([]byte, 1024*4)
f, err := os.Create(fileName)
if err != nil {
return
}
for {
n, err := conn.Read(buf)
if err != nil {
if err == io.EOF {
fmt.Printf("文件传送完成")
break
}
return
}
if n == 0 {
fmt.Printf("文件传送完成")
break
}
f.Write(buf[:n])
}
}
// 发送方代码
package main
import (
"fmt"
"io"
"net"
"os"
)
func main() {
fmt.Println("请输入要传输的文件路径")
var path string
fmt.Scan(&path)
fileInfo, err0 := os.Stat(path)
if err0 != nil {
return
}
//传递 文件名给 文件服务器
conn, err := net.Dial("tcp", "10.0.154.199:8899")
if err != nil {
return
}
defer conn.Close()
conn.Write([]byte(fileInfo.Name()))
buf := make([]byte, 1024)
n, err1 := conn.Read(buf)
if err1 != nil {
return
}
if string(buf[:n]) == "ok" {
// 开始传输文件
fmt.Println("接收到ok")
sendFile(path, conn)
}
}
func sendFile(path string, conn net.Conn) {
//读取文件
f, err := os.Open(path)
if err != nil {
return
}
buf := make([]byte, 1024*4)
for {
n, err1 := f.Read(buf)
if err1 != nil {
if err1 == io.EOF {
fmt.Println("传送成功")
return
}
fmt.Println("传送失败")
}
conn.Write(buf[:n])
}
}
go实现--聊天室---代码
服务器代码实现
package main
import (
"fmt"
"log"
"net"
)
type Client struct {
C chan string
Addr string
Name string
}
// var onLineMap map[string]Client 这样没有分配内存,因为map是引用类型
var onLineMap = make(map[string]Client)
var message = make(chan string)
func addToOnline(conn net.Conn) {
defer conn.Close()
// 获取ip地址
str := conn.RemoteAddr().String() // 将*net.TCPAddr指针类型的变为string类型
// 创建一个结构实列,然后添加到在线map中
client := Client{make(chan string), str, str}
onLineMap[str] = client
go WriteToClient(client, conn)
// 发送已经上线
message <- makeMessage(str, "login")
// 是否主动退出
quit := make(chan bool)
// 遍历map存在多少人
// 新建一个协程,监听客户端发送的消息
go func(addr string, conn net.Conn) {
buf := make([]byte, 1024)
for {
n, err := conn.Read(buf)
if err != nil {
return
}
str := string(buf[:n])
if str == "who" {
for _, v := range onLineMap {
// fmt.Println(v.Name)
message <- makeMessage(v.Addr, "在线\n")
}
message <- string(len(onLineMap)) + "在线\n"
} else if str == "exit" {
quit <- true
} else {
message <- makeMessage(addr, str)
}
}
}(str, conn)
fmt.Println("---------------")
for _, v := range onLineMap {
fmt.Println(v.Name)
}
for {
select {
case <-quit:
message <- makeMessage(str, "logout")
delete(onLineMap, str) // 删除map
}
}
}
func reciveMessage() {
for {
msg := <-message // 没有消息时这个协程 会阻塞
// 遍历map 给每个人发送
for _, v := range onLineMap {
v.C <- msg
}
}
}
func WriteToClient(cli Client, conn net.Conn) {
for msg := range cli.C {
// 给当前客户端发送信息
conn.Write([]byte(msg))
}
}
func makeMessage(addr string, meg string) (result string) {
result = "[" + addr + "] : " + meg
return
}
func main() {
//监听服务
listener, err := net.Listen("tcp", "10.0.154.199:8899")
defer listener.Close()
if err != nil {
return
}
// 接收消息
go reciveMessage()
// 循环接收连接请求
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
continue
}
go addToOnline(conn)
}
}
网友评论