项目地址
https://github.com/cmdch2017/http_tcpServer
项目结构
如何快速上手
http篇
1、controller包就相当于@RestController,这里返回了一个Person对象,当你需要新建一个接口时,再新写一个func仿照下面的方法就行了
package controller
import (
"net/http"
"testproject12/common"
"testproject12/entity"
"testproject12/util"
)
// PersonHandler 无入参,返回person类
func PersonHandler(w http.ResponseWriter, r *http.Request) {
// 创建一个Person对象
person := entity.Person{
Name: "John Doe",
Age: 30,
Title: "Software Engineer",
}
messageHex := "FFFFFF"
util.SendHexMessageToAllUser(messageHex)
// 封装为JSON格式的CommonResult并写入响应体
common.WriteJSONResponse(w, http.StatusOK, common.DefaultSuccessMsg, person)
}
2、router.go负责配置路由,下面的代码中,server.AddRoute的key相当于@RequestMapping(“/person”),value是上面文件在controller包下,方法是PersonHandler
package router
import (
"testproject12/controller"
"testproject12/httpServer"
)
func SetupRoutes(server *httpServer.HTTPServer) {
// 添加路由
server.AddRoute("/person", controller.PersonHandler)
// Add more routes as needed
}
tcp篇
用SocketTool新建一个客户端
http://localhost:8080/person
服务器收到数据FFFFFF
总结
实现了http请求与tcp请求,如果有需要的话请fork我的github代码
性能
附录
完整代码
package common
import (
"encoding/json"
"fmt"
"net/http"
)
// Constants for CommonResult keys
const (
CodeTag = "code"
MsgTag = "msg"
DataTag = "data"
)
// Default success and failure messages
const (
DefaultSuccessMsg = "操作成功"
DefaultFailedMsg = "操作失败"
)
// CommonResult creates a new CommonResult object with the given code and message
func CommonResult(code int, msg string) map[string]interface{} {
return map[string]interface{}{
CodeTag: code,
MsgTag: msg,
}
}
func CommonResultWithData(code int, msg string, data interface{}) map[string]interface{} {
result := CommonResult(code, msg)
if data != nil {
result[DataTag] = data
}
return result
}
// Success returns a CommonResult representing success with an optional data payload
func Success(data ...interface{}) map[string]interface{} {
result := CommonResult(HttpStatusSuccess, DefaultSuccessMsg)
if len(data) > 0 {
result[DataTag] = data[0]
}
return result
}
// Error returns a CommonResult representing an error with an optional data payload
func Error(msg string, data ...interface{}) map[string]interface{} {
result := CommonResult(HttpStatusError, msg)
if len(data) > 0 {
result[DataTag] = data[0]
}
return result
}
// HttpStatus constants
const (
HttpStatusSuccess = iota
HttpStatusError
)
func WriteJSONResponse(w http.ResponseWriter, code int, msg string, data interface{}) {
// 创建一个CommonResult并将数据放入其中
result := CommonResultWithData(code, msg, data)
// 将CommonResult对象序列化为JSON格式的字符串
resultData, err := json.Marshal(result)
if err != nil {
fmt.Println("json格式化错误")
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
// 设置响应头为JSON格式
w.Header().Set("Content-Type", "application/json")
// 将JSON数据写入响应体
w.Write(resultData)
}
package controller
import (
"net/http"
"testproject12/common"
"testproject12/entity"
"testproject12/util"
)
// PersonHandler 无入参,返回person类
func PersonHandler(w http.ResponseWriter, r *http.Request) {
// 创建一个Person对象
person := entity.Person{
Name: "John Doe",
Age: 30,
Title: "Software Engineer",
}
messageHex := "FFFFFF"
util.SendHexMessageToAllUser(messageHex)
// 封装为JSON格式的CommonResult并写入响应体
common.WriteJSONResponse(w, http.StatusOK, common.DefaultSuccessMsg, person)
}
package entity
import "net"
type ClientInfo struct {
Conn net.Conn
}
package entity
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Title string `json:"title"`
}
package httpServer
import (
"fmt"
"net/http"
)
// HTTPServer represents an HTTP tcpserver
type HTTPServer struct {
routes map[string]http.HandlerFunc
}
// NewHTTPServer creates a new HTTPServer instance
func NewHTTPServer() *HTTPServer {
return &HTTPServer{
routes: make(map[string]http.HandlerFunc),
}
}
// AddRoute adds a new route to the HTTP tcpserver
func (s *HTTPServer) AddRoute(path string, handler http.HandlerFunc) {
s.routes[path] = handler
}
// RunHTTPServer starts the HTTP tcpserver and sets up the routes
func (s *HTTPServer) RunHTTPServer() {
for path, handler := range s.routes {
// 添加http路由
http.HandleFunc(path, handler)
}
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Println("HTTP服务器启动失败:", err)
}
}
package main
import (
"testproject12/httpServer"
"testproject12/router"
"testproject12/tcpserver"
)
func main() {
// 创建并运行TCP服务器
go tcpserver.NewServer().RunTCPServer()
// 创建HTTP服务器
httpserver := httpServer.NewHTTPServer()
// 设置路由
router.SetupRoutes(httpserver)
// 启动HTTP服务器
go httpserver.RunHTTPServer()
select {}
}
package router
import (
"testproject12/controller"
"testproject12/httpServer"
)
func SetupRoutes(server *httpServer.HTTPServer) {
// 添加路由
server.AddRoute("/person", controller.PersonHandler)
// Add more routes as needed
}
package tcpserver
import (
"encoding/hex"
"fmt"
"net"
"sync"
"testproject12/entity"
)
// 所有用户信息
var AllConnectionList []net.Conn
// Server 服务端结构体
type Server struct {
Clients map[string]entity.ClientInfo
Mutex sync.Mutex
}
// NewServer creates a new Server instance
func NewServer() *Server {
return &Server{
Clients: make(map[string]entity.ClientInfo),
}
}
func SendHexMessage(conn net.Conn, hexMessage string) error {
messageBytes, err := hex.DecodeString(hexMessage)
if err != nil {
fmt.Println("转换错误", err)
return err
}
_, err = conn.Write(messageBytes)
if err != nil {
fmt.Println("发送消息失败", err)
return err
}
return nil
}
// RemoveConnection removes a connection from AllConnectionList
func RemoveConnection(conn net.Conn) {
for i, c := range AllConnectionList {
if c == conn {
AllConnectionList = append(AllConnectionList[:i], AllConnectionList[i+1:]...)
break
}
}
}
// RunTCPServer starts the TCP tcpserver
func (s *Server) RunTCPServer() {
fmt.Println("服务端启动了")
listen, err := net.Listen("tcp", "0.0.0.0:8888")
if err != nil {
fmt.Println("监听失败", err)
return
}
// 循环等待客户端的连接
for {
conn, err := listen.Accept()
if err != nil {
fmt.Println("客户端的等待失败", err)
return
} else {
fmt.Printf("等待连接成功:,con=%v,接受到的客户端信息:%v \n", conn, conn.RemoteAddr().String())
// 服务端主动发送消息给客户端
messageHex := "48656c6c6f2066726f6d20736572766572" // "Hello from tcpserver" 的十六进制表示
SendHexMessage(conn, messageHex)
}
// 处理客户端连接的协程
go s.handleClient(conn)
}
}
// 处理客户端连接
func (s *Server) handleClient(conn net.Conn) {
defer conn.Close()
// 获取客户端地址
clientAddr := conn.RemoteAddr().String()
// 将客户端信息存储到 map 中
s.Mutex.Lock()
s.Clients[clientAddr] = entity.ClientInfo{
Conn: conn, // 存储客户端连接对象
}
AllConnectionList = append(AllConnectionList, conn)
s.Mutex.Unlock()
// 处理客户端消息
for {
buf := make([]byte, 1024)
n, err := conn.Read(buf)
if err != nil {
break
}
// 处理接收到的消息
hexData := hex.EncodeToString(buf[:n])
fmt.Println("收到客户端消息:", clientAddr, ":", hexData)
}
// 客户端断开连接,从 map 中移除该用户
s.Mutex.Lock()
delete(s.Clients, clientAddr)
RemoveConnection(conn)
s.Mutex.Unlock()
fmt.Println("客户端断开连接:", clientAddr)
}
package util
import (
"encoding/hex"
"testproject12/tcpserver"
)
// SendHexMessage 发送十六进制消息
// SendHexMessageToAllUser 广播发送十六进制消息
func SendHexMessageToAllUser(message string) {
messageHex := hex.EncodeToString([]byte(message))
for _, conn := range tcpserver.AllConnectionList {
tcpserver.SendHexMessage(conn, messageHex)
}
}
Dockerfile
# Use the official Golang image as the base image
FROM golang:1.21-alpine
# Set the working directory inside the container
WORKDIR /go/src/app
# Copy the contents of the current directory to the working directory inside the container
COPY . .
# Build the Go application
RUN go build -o abc ./main
# Add executable permission to the main binary
RUN chmod +x ./abc
# Expose the port the application runs on
EXPOSE 8888 8080
# Define the command to run the application
CMD ["./abc"]
go.mod
module testproject12
go 1.21.4