无框架Java转go语言写http与tcp请求

项目地址

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/256152.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GaussDB数据库表创建行访问控制策略

目录 一、前言 二、GaussDB中的行访问控制 1、CREATE ROW LEVEL SECURITY POLICY语法 2、ALTER ROW LEVEL SECURITY POLICY语法 3、ROW LEVEL SECURITY策略与适配SQL语法关系 三、GaussDB中的行访问控制策略示例 1、实现GaussDB行访问控制的一般步骤 2、行访问控制策略…

AWS解决方案架构师学习与备考

系列文章目录 送书第一期 《用户画像:平台构建与业务实践》 送书活动之抽奖工具的打造 《获取博客评论用户抽取幸运中奖者》 送书第二期 《Spring Cloud Alibaba核心技术与实战案例》 送书第三期 《深入浅出Java虚拟机》 送书第四期 《AI时代项目经理成长之道》 …

信息收集 - 网站服务器

操作系统 区分大小写: 如果修改首页或其他页面的大小写后,网站返回一个错误页面,例如报错 "404 Not Found" 或类似的错误,这可能意味着网站运行在 Linux 或类 Unix 操作系统上。这是因为大多数 Linux 系统是区分大小写的。如果修改大小写后,网站页面正常显示,这…

maui中实现加载更多 RefreshView跟ListView(2)

一个类似商品例表的下拉效果&#xff1a; 代码 新增个类为商品商体类 public class ProductItem{public string ImageSource { get; set; }public string ProductName { get; set; }public string Price { get; set; }}界面代码&#xff1a; <?xml version"1.0&quo…

人体关键点检测4:C/C++实现人体关键点检测(人体姿势估计)含源码 可实时检测

人体关键点检测4&#xff1a;C/C实现人体关键点检测(人体姿势估计)含源码 可实时检测 目录 人体关键点检测4&#xff1a;C/C实现人体关键点检测(人体姿势估计)含源码 可实时检测 1.项目介绍 2.人体关键点检测方法 (1)Top-Down(自上而下)方法 (2)Bottom-Up(自下而上)方法&…

Vue--第十天

终极实战----大事件项目 1.简介&#xff1a; 2.创建项目&#xff1a; 1.创建&#xff08;159-163&#xff09;&#xff1a; 还是对着视频操作吧 2.路由&#xff1a; 3.element Plus: 导入element Plus 后不需要再导入插件配置&#xff0c;就连组件导入也不用 4.pinia构建用…

【C盘清理】Jetbrains全家桶(PyCharm、Clion……)更改 IDE 特定文件(配置、缓存、插件、日志等)存储位置

文章目录 一、官网说明二、更改 IDE 目录的位置1. 转到“帮助”|“编辑自定义属性”2. 各文件位置3. 以PyCharm系统目录为例4. 修改idea.properties 三、清理旧的 IDE 目录 一、官网说明 IDE 使用的目录官网说明 二、更改 IDE 目录的位置 默认情况下&#xff0c;PyCharm 将每…

pytorch——豆瓣读书评价分析

任务目标 基于给定数据集&#xff0c;采用三层bp神经网络方法&#xff0c;编写程序并构建分类模型&#xff0c;通过给定特征实现预测的书籍评分的模型。 选取数据 在各项指标中&#xff0c;我认为书籍的评分和出版社、评论数量还有作者相关&#xff0c;和其他属性的关系并大。…

vscode如何开发微信小程序?(保姆级教学)

1.安装“微信小程序开发工具”扩展 2.安装“vscode weapp api”扩展 3.安装“vscode wxml”扩展 4.安装“vscode-wechat”扩展 5.在终端执行命令&#xff1a; vue create -p dcloudio/uni-preset-vue uniapp-test uniapp-test就是我这里的项目名称了 6.如果遇到了这个错误&a…

云渲染插件怎么设置?云渲染插件设置教程

云渲染技术以其高效、便捷的特性正改变着3D设计和视频制作行业。为了进一步简化渲染过程&#xff0c;云渲染插件应运而生。云渲染插件可以让用户在熟悉的3D软件环境中直接完成渲染任务&#xff0c;大幅提高工作的连贯性与效率。那么如何在3D软件中安装和设定这些神奇的云渲染插…

【为数据之道学习笔记】5-7五类数据主题联接的应用场景

在数字化转型的背景下&#xff0c;华为的数据消费已经不再局限于传统的报表分析&#xff0c;还要支持用户的自助分析、实时分析&#xff0c;通过数据的关联&#xff0c;支持业务的关联影响分析以及对目标对象做特征识别&#xff0c;进行特定业务范围圈定、差异化管理与决策等。…

传奇的GEE、翎风、V8引擎之间的区别,哪个引擎更好用?

我们在选择传奇版本时可以看到有很多GEE引擎的版本&#xff0c;同时也有少数的翎风和V8引擎版本&#xff0c;当我们选择的版本是翎风或是v8引擎&#xff0c;之前没有架设过怎么办呢&#xff1f;不要着急&#xff0c;往下看&#xff01; 这还得从GEE引擎说起&#xff0c;GEE引擎…

「数据结构」二叉树1

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;C启航 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 文章目录 &#x1f349;树&#x1f349;二叉树&#x1f34c;特殊二叉树&#x1f34c;二叉树的性质&#x1f34c;存储结构 &#x1f349;…

【具身智能评估9】Open X-Embodiment: Robotic Learning Datasets and RT-X Models

论文标题&#xff1a;Open X-Embodiment: Robotic Learning Datasets and RT-X Models 论文作者&#xff1a;– 论文原文&#xff1a;https://arxiv.org/abs/2310.08864 论文出处&#xff1a;– 论文被引&#xff1a;–&#xff08;12/18/2023&#xff09; 论文代码&#xff1a…

Antd Select 添加中框

默认antd 的 Select中间并没有竖框&#xff0c;但是ui design设计了&#xff0c;所以记录一下如何添加 默认&#xff1a; CSS&#xff1a; .custom-select-suffix-icon {display: flex;align-items: center; }.custom-select-suffix-icon::before {content: ;height: 31px; …

使用cdn加速导致Vue.js devtools 工具不能使用

打包分析 npm run preview -- --report发现 element-ui mock.js&#xff08;模拟数据&#xff09; cos-js-sdk-v5.js&#xff08;腾讯云上传&#xff09;过大使用cdn加速 2. cdn 加速 webpack排除打包 vue.config.js configureWebpack: {name: name,resolve: {alias: {: reso…

Mybatis-Plus之内置接口(一起了解Mybatis-Plus的内置接口)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringBoot开发之Mybatis-Plus系列》。&#x1…

Python使用HTTP库发送GET请求的示例——轻松探索网络世界

大家好&#xff0c;今天我要给大家介绍一个非常实用的Python库——HTTP库&#xff0c;它可以帮助我们轻松地发送HTTP请求。今天&#xff0c;我们就来学习一下如何使用HTTP库发送GET请求。 首先&#xff0c;我们需要安装HTTP库。如果你还没有安装&#xff0c;可以通过pip命令进…

补题与总结:AtCoder Beginner Contest 333 D、E

文章目录 写在最前面的复盘D - Erase LeavesE - Takahashi Quest 写在最前面的复盘 前三题属于是凑数题&#xff0c;下次争取快点a掉&#xff0c;这次wa了一次 C题写了个三指针&#xff0c;从小到大枚举出满足题意的数&#xff0c;其实可以直接暴力枚举满足题意的数&#xff0c…

Vue框架入门(项目搭建)

VUE文档 https://cn.vuejs.org/guide/introduction.html SFC名词介绍 SFC即 *.vue 文件&#xff0c;英文 Single-File Component&#xff0c;简称 SFC 每一个 *.vue 文件都由三种顶层语言块构成&#xff1a;<template>、<script> 和 <style> template​ 每个…
最新文章