用Go写一个简单的TCP server or client 模型

这篇博客介绍了如何使用Go语言编写一个简单的TCP server和client。通过封装net/Conn,创建了两个goroutine分别处理Read和Write,确保线程安全。服务器端实现包括监听端口、接受连接并开启读写线程,客户端则在建立连接后同样处理读写。文章提供了简单的使用示例,但未涉及心跳检测和封包解包的详细实现。
摘要由CSDN通过智能技术生成

对Conn封装的基本思路

go内置了net包已经很好的封装了socket通讯。然而在实际使用中,由于net/Conn的Read/Write方法是堵塞的原因,必须将其放入单独的goroutine中进行处理。

我们先简单的整理下思路,对于连接(Conn)的处理,我们可以开启2条goroutine进行处理,一条用于堵塞的Read的处理,另一条进行Write的处理。

这里必须指出,其实Write本身就是线程安全的,也就是我们在别的任何地方都可以进行Write,但是Write是堵塞的,所以考虑到这点,我们还是将其放入一个单独的goroutine中进行处理。

这样设计的原因在于Conn是支持同时Read/Write的,这样我们的基本的Conn的模型就成型了。对于服务端或者客户端而言,我们只需要封装对应过来的Conn即可,Conn的读写goroutine进行处理,并将获得的事件抛向外部。

那么我们就按这个思路来实现一个简单的Connection封装,该封装支持线程安全的写,并且支持解包操作。

package tcpnetwork

import (
    "errors"
    "log"
    "net"
    "time"
)

const (
    kConnStatus_None = iota
    kConnStatus_Connected
    kConnStatus_Disconnected
)

const (
    kConnEvent_None = iota
    kConnEvent_Connected
    kConnEvent_Disconnected
    kConnEvent_Data
    kConnEvent_Close
)

const (
    kConnConf_DefaultSendTimeoutSec = 5
    kConnConf_MaxReadBufferLength   = 0xffff // 0xffff
)

type Connection struct {
    conn                net.Conn
    status              int
    connId              int
    sendMsgQueue        chan []byte
    sendTimeoutSec      int
    eventQueue          IEventQueue
    streamProtocol      IStreamProtocol
    maxReadBufferLength int
    userdata            interface{}
    from                int
    readTimeoutSec      int
}

func newConnection(c net.Conn, sendBufferSize int, eq IEventQueue) *Connection {
    return &Connection{
        conn:                c,
        status:              kConnStatus_None,
        connId:              0,
        sendMsgQueue:        make(chan []byte, sendBufferSize),
        sendTimeoutSec:      kConnConf_DefaultSendTimeoutSec,
        maxReadBufferLength: kConnConf_MaxReadBufferLength,
        eventQueue:          eq,
    }
}

type ConnEvent struct {
    EventType int
    Conn      *Connection
    Data      []byte
}

func newConnEvent(et int, c *Connection, d []byte) *ConnEvent {
    return &ConnEvent{
        EventType: et,
        Conn:      c,
        Data:      d,
    }
}

//  directly close, packages in queue will not be sent
func (this *Connection) close() {
    if kConnStatus_Connected != this.status {
        return
    }

    this.conn.Close()
    this.status = kConnStatus_Disconnected
}

func (this *Connection) Close() {
    if this.status != kConnStatus_Connected {
        return
    }

    select {
    case this.sendMsgQueue <- nil:
        {
            //  nothing
当然可以!下面是一个基于Java的TCP ServerTCP Client的例子: TCP Server(服务器端): ```java import java.io.*; import java.net.*; public class TCPServer { public static void main(String[] args) { try { // 创建ServerSocket对象,指定监听的端口号 ServerSocket serverSocket = new ServerSocket(8888); System.out.println("Server started. Waiting for client..."); // 监听客户端的连接请求 Socket clientSocket = serverSocket.accept(); System.out.println("Client connected."); // 获取输入流,用于接收客户端发送的数据 InputStream inputStream = clientSocket.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); // 获取输出流,用于向客户端发送数据 OutputStream outputStream = clientSocket.getOutputStream(); PrintWriter printWriter = new PrintWriter(outputStream); String message; while ((message = bufferedReader.readLine()) != null) { System.out.println("Received from client: " + message); // 处理客户端发送的数据(这里简单地将接收到的消息原样返回给客户端) printWriter.println(message); printWriter.flush(); } // 关闭资源 bufferedReader.close(); printWriter.close(); clientSocket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` TCP Client(客户端): ```java import java.io.*; import java.net.*; public class TCPClient { public static void main(String[] args) { try { // 创建Socket对象,指定连接的服务器IP和端口号 Socket socket = new Socket("localhost", 8888); // 获取输入流,用于接收服务器发送的数据 InputStream inputStream = socket.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); // 获取输出流,用于向服务器发送数据 OutputStream outputStream = socket.getOutputStream(); PrintWriter printWriter = new PrintWriter(outputStream); // 发送数据到服务器 String message = "Hello, server!"; printWriter.println(message); printWriter.flush(); // 接收服务器返回的数据 String response; if ((response = bufferedReader.readLine()) != null) { System.out.println("Received from server: " + response); } // 关闭资源 bufferedReader.close(); printWriter.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 这是一个简单的例子,TCP Server监听指定端口,TCP Client连接到服务器并发送一条消息,然后服务器将收到的消息原样返回给客户端。你可以根据自己的需求进行相应的修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值