Golang 및nginx-lua의 tcp 통신 코드를 기록합니다
9282 단어 golang
package main
import (
"log"
"net"
"strconv"
"strings"
"sync"
"time"
)
const (
msg_length = 10240
)
type Control struct {
conn net.TCPConn
mutex sync.Mutex
}
//store request map
var requestMap map[string]*Control
func proxy(conn *net.TCPConn) {
defer conn.Close()
var data = make([]byte, 1024)
for {
_, err := conn.Read(data)
if err != nil {
log.Println("proxy disconnect from " + conn.RemoteAddr().String())
return
}
var commands = strings.Split(string(data), " ")
if len(commands) <= 1 || commands[1] == "" {
log.Println("proxy receive bad commands : " + string(data))
return
}
var id = commands[0]
var n, tn int
if rclient, ok := requestMap[id]; ok {
log.Println("client " + commands[0] + " do command " + commands[1])
_, err = rclient.conn.Write([]byte(commands[1] + "\r
"))
if err != nil {
rclient.conn.Close()
delete(requestMap, id)
break
}
var msglen = 0
var msg []string
var tdata = make([]byte, 2048)
var rdata []byte
tn = 0
for {
rclient.mutex.Lock()
rclient.conn.SetReadDeadline(time.Now().Add(1 * time.Millisecond))
n, err = rclient.conn.Read(tdata)
rclient.mutex.Unlock()
if err != nil {
if strings.HasSuffix(err.Error(), "timeout") == false {
rclient.conn.Close()
delete(requestMap, id)
break
}
}
if n > 0 {
if tn == 0 && n > 0 {
msg = strings.Split(string(tdata[:n]), "_")
msglen, err = strconv.Atoi(msg[0])
if err != nil {
break
}
rdata = append(rdata, tdata[len(msg[0])+1:n]...)
} else {
rdata = append(rdata, tdata[0:n]...)
}
tn = tn + n
if tn >= msglen+len(msg[0])+1 {
break
}
}
}
conn.Write(rdata[:msglen])
} else {
log.Println("client is offline " + id)
conn.Write([]byte("offline"))
}
break
}
}
//
func TcpMain(ip string, port int, router bool) {
//start tcp server
listen, err := net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP(ip), port, ""})
if err != nil {
log.Fatalln("listen port error")
return
}
log.Println("start tcp server " + ip + " " + strconv.Itoa(port))
defer listen.Close()
//listen new request
var id string
for {
conn, err := listen.AcceptTCP()
if err != nil {
log.Println("receive connection failed")
continue
}
if router == true {
var tdata = make([]byte, 256)
conn.SetReadDeadline(time.Now().Add(3 * time.Second))
var n, err = conn.Read(tdata)
if err != nil {
conn.Close()
continue
}
id = string(tdata[0:n])
if rcontrol, ok := requestMap[id]; ok {
rcontrol.mutex.Lock()
rcontrol.conn.Close()
rcontrol.mutex.Unlock()
delete(requestMap, id)
}
log.Println("connected from " + id + " addr " + conn.RemoteAddr().String())
var control = &Control{}
control.conn = *conn
requestMap[id] = control
} else {
go proxy(conn)
}
}
}
func main() {
requestMap = make(map[string]*Control)
go TcpMain("127.0.0.1", 1988, false)
TcpMain("0.0.0.0", 1987, true)
}
nginx-lua 설정은 다음과 같다(그중 lua-resty-http 사용이 버전)
lua_package_path "/usr/local/openresty/nginx/conf/lua-resty-http-master/lib/?.lua;;";
init_worker_by_lua_file /usr/local/openresty/nginx/conf/connect.lua;
lua_socket_keepalive_timeout 600;
conf/connect.lua 코드는 다음과 같습니다.
local function proxy()
local shutdown = 0
while true do
if ngx.worker.exiting() then
break
end
local tcpsocket = ngx.socket.tcp()
local ok, err = tcpsocket:connect("127.0.0.1", 1987)
if not ok then
ngx.timer.at(5,proxy)
break
else
tcpsocket:send("0")
while true do
if ngx.worker.exiting() then
shutdown = 1
break
end
local result = ""
tcpsocket:settimeout(600000)
local line, err, partial = tcpsocket:receive()
if not line then
tcpsocket:close()
break
else
line = string.gsub(line, "^%s*(.-)%s*$", "%1")
local http = require("resty.http")
local httpc = http.new()
local res, err = httpc:request_uri("http://www.ciaos.com"..line, {
method = "POST",
body = "username=root",
headers = {
["Content-Type"] = "application/x-www-form-urlencoded",
}
})
if not res then
tcpsocket.send("0_err")
else
local len = string.len(res.body)
tcpsocket:send(len .. "_" .. res.body)
end
end
end
if shutdown == 1 then
break
end
end
end
end
local ok, err = ngx.timer.at(0,proxy)
if not ok then
ngx.log(ngx.ERR, "timer error")
end
php 테스트 코드
public function console()
{
$command= $this->input->get("cmd");
if(is_null($command) or $command == false){
echo "cmd not found";
return;
}
$port = 1988;
$ip = "127.0.0.1";
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket < 0) {
echo "socket_create() failed: reason: " . socket_strerror($socket) . "
";
return;
}
$result = socket_connect($socket, $ip, $port);
if ($result < 0) {
echo "socket_connect() failed.
Reason: ($result) " . socket_strerror($result) . "
";
return;
}
$in = "0 $command end";
if(!socket_write($socket, $in, strlen($in))) {
echo "socket_write() failed: reason: " . socket_strerror($socket) . "
";
}else {
}
$out = socket_read($socket, 8192);
echo $out;
socket_close($socket);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
set containerThere is no built-in set container in Go How to implement Set struct{} => type struct{}{} => 0bytes How to create set :=...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.