这是我在服务器每秒充满过多数据包时遇到的错误:
2014/11/28 12:52:49 main.go:59: loading plugin: print
2014/11/28 12:52:49 main.go:86: starting server on 0.0.0.0:8080
2014/11/28 12:52:59 server.go:15: client has connected: 127.0.0.1:59146
2014/11/28 12:52:59 server.go:43: received data from client 127.0.0.1:59146: &main.Observation{SensorId:"1", Timestamp:1416492023}
2014/11/28 12:52:59 server.go:29: read error from 127.0.0.1:59146: zlib: invalid header
2014/11/28 12:52:59 server.go:18: closing connection to: 127.0.0.1:59146
它设法解码一个数据包(有时,可能是2或3),然后输出错误。这是执行洪水的代码:
import socket
import struct
import json
import zlib
import time
def serialize(data):
data = json.dumps(data)
data = zlib.compress(data)
packet = struct.pack('!I', len(data))
packet += data
return len(data), packet
message = {
'sensor_id': '1',
'timestamp': 1416492023,
}
length, buffer = serialize([message])
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 8080))
while True:
client.send(buffer)
#time.sleep(0.0005)
当我取消注释time.sleep()
调用时,服务器运行正常。似乎太多的数据包/每秒都在扼杀服务器。为什么呢?
这是相关的Go代码。连接处理程序:
func (self *Server) handleConnection(connection net.Conn) {
for {
connection.SetReadDeadline(time.Now().Add(30 * time.Second))
observations, err := self.Protocol.Unserialize(connection)
if err != nil {
log.Printf("read error from %s: %s\n", connection.RemoteAddr(), err)
return
}
}
这是解串器:
// Length Value protocol to read zlib compressed, JSON encoded packets.
type ProtocolV2 struct{}
func (self *ProtocolV2) Unserialize(packet io.Reader) ([]*Observation, error) {
var length uint32
if err := binary.Read(packet, binary.BigEndian, &length); err != nil {
return nil, err
}
buffer := make([]byte, length)
rawreader := bufio.NewReader(packet)
if _, err := rawreader.Read(buffer); err != nil {
return nil, err
}
bytereader := bytes.NewReader(buffer)
zreader, err := zlib.NewReader(bytereader)
if err != nil {
return nil, err
}
defer zreader.Close()
var observations []*Observation
decoder := json.NewDecoder(zreader)
if err := decoder.Decode(&observations); err != nil {
return nil, err
}
return observations, nil
}
答案 0 :(得分:0)
Python脚本中的客户端似乎存在错误。
不检查client.send的返回,因此脚本不会以正确的方式处理部分写入。基本上,当套接字缓冲区已满时,只会写入部分消息,导致服务器无法解码消息。
此代码已损坏,但添加等待使其工作,因为它会阻止套接字缓冲区已满。
您可以使用client.sendall来确保写操作完成。
Python文档中的更多信息:
https://docs.python.org/2/library/socket.html
https://docs.python.org/2/howto/sockets.html#using-a-socket
现在在Go服务器中,也存在类似的问题。文档说:
读取将数据读入p。它返回读入p的字节数。它在底层Reader上最多调用一次,因此n可能小于len(p)。在EOF,计数将为零,错误将为io.EOF。
rawreader.Read调用可能返回的字节数少于预期。您可能希望使用io包的ReadFull()函数来确保读取完整的消息。