summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/main.go76
-rw-r--r--tester.py79
2 files changed, 127 insertions, 28 deletions
diff --git a/server/main.go b/server/main.go
index ec848ad..7c67ead 100644
--- a/server/main.go
+++ b/server/main.go
@@ -2,7 +2,6 @@ package main
import (
"encoding/json"
- "fmt"
"log"
"net"
)
@@ -36,13 +35,49 @@ func parseMessage(data []byte) Message {
return m
}
+func toBytes(num uint32) []byte {
+ buf := make([]byte, 4)
+ var mask uint32 = 0x00FF
+ for i := 0; i < 4; i += 1 {
+ buf[4-i-1] = byte(num & mask)
+ num >>= 8
+ }
+ return buf
+}
+
+func fromBytes(data []byte) uint32 {
+ var num uint32
+ for i := 0; i < 4; i += 1 {
+ num += uint32(data[i] << ((4 - i - 1) * 8))
+ }
+ return num
+}
+
+func sendMessage(conn net.Conn, message []byte) error {
+ size := uint32(len(message))
+
+ _, err := conn.Write(toBytes(size))
+ if err != nil {
+ return err
+ }
+
+ _, err = conn.Write(message)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
func handleConnection(conn net.Conn) {
defer conn.Close()
+ // 1 мегабайт
+ var maxBodySize uint32 = 1048576
maxAuthAttempts := 5
authAttempts := 0
authenticated := false
- buf := make([]byte, 4096)
+ buf := make([]byte, 256)
for {
if authAttempts >= maxAuthAttempts {
@@ -50,16 +85,30 @@ func handleConnection(conn net.Conn) {
Status: FAILURE,
Data: "Превышено количество неавторизованных запросов",
})
- _, _ = conn.Write(resp)
+
+ _ = sendMessage(conn, resp)
break
}
- readLen, err := conn.Read(buf)
+ _, err := conn.Read(buf)
if err != nil {
break
}
- message := parseMessage(buf[:readLen])
+ size := fromBytes(buf[:4])
+ if size > maxBodySize {
+ resp, _ := json.Marshal(Response{
+ Status: FAILURE,
+ Data: "Превышен максимальный размер запроса",
+ })
+
+ _ = sendMessage(conn, resp)
+ break
+ }
+
+ rawMessage := buf[4 : size+4]
+ message := parseMessage(rawMessage)
+ //fmt.Println(message.Data)
if message.Type == AUTHENTICATE {
// TODO(andrew): Добавить процесс аутентификации
if true {
@@ -72,28 +121,26 @@ func handleConnection(conn net.Conn) {
Status: FAILURE,
Data: "Для работы с сервером необходима аутентификация",
})
- _, err = conn.Write(resp)
+
+ err = sendMessage(conn, resp)
if err != nil {
- conn.Close()
break
- } else {
- authAttempts += 1
- continue
}
+
+ authAttempts += 1
+ continue
}
if message.Data == "exit" {
break
}
- fmt.Println(message.Data)
resp, _ := json.Marshal(Response{
Status: SUCCESS,
Data: "some data",
})
- _, err = conn.Write(resp)
+ err = sendMessage(conn, resp)
if err != nil {
- err = conn.Close()
break
}
}
@@ -101,6 +148,7 @@ func handleConnection(conn net.Conn) {
func main() {
sock, err := net.Listen("tcp", "localhost:8080")
+ defer sock.Close()
handleError(err)
for {
@@ -108,7 +156,7 @@ func main() {
if err == nil {
go handleConnection(conn)
} else {
- break
+ handleError(err)
}
}
}
diff --git a/tester.py b/tester.py
index d5e9f32..265d99b 100644
--- a/tester.py
+++ b/tester.py
@@ -1,23 +1,74 @@
-from socket import socket, SOCK_STREAM
+from socket import socket
import json
+from time import sleep, time
+
MESSAGE, AUTHENTICATE, RENAME = "message", "authenticate", "rename"
-with socket() as sock:
- addr = host, port = "localhost", 8080
- print(addr)
- sock.connect(addr)
- for i in range(1000):
- print(f"Sending {i} request")
+def int_from_bytes(data: bytes) -> int:
+ num = 0
+ for i, byte in enumerate(data):
+ num += byte << ((4 - i - 1) * 8)
+ return num
+
+
+def to_bytes(num: int) -> bytes:
+ b = bytearray(4)
+ mask = 0xFF
+ for i in range(4):
+ b[4 - i - 1] = num & mask
+ num >>= 8
+ return bytes(b)
+
+
+def send_message(connection: socket, data: bytes):
+ size = len(data)
+ b = to_bytes(size)
+ # print(size, list(map(int, b)))
+ connection.sendall(b + data)
+
+
+def main():
+ with socket() as sock:
+ addr = host, port = "localhost", 8080
+ print(addr)
+ sock.connect(addr)
+
+ t1 = time()
+
request = {
- "type": "message",
- "data": f"hello, {i}",
+ "type": AUTHENTICATE,
+ "data": "auth",
"user": "andrew"
}
- sock.sendall(json.dumps(request).encode())
- print("Waiting for response")
- response = sock.recv(4096).decode()
- print(f"Response: {response}")
+ send_message(sock, json.dumps(request).encode())
+
+ for i in range(10000):
+ print(f"Sending {i} request")
+ request = {
+ "type": MESSAGE,
+ "data": f"hello, {i}",
+ "user": "andrew"
+ }
+ send_message(sock, json.dumps(request).encode())
+
+ print("Waiting for response")
+ response = sock.recv(4)
+ size = int_from_bytes(response)
+ # print(f"Size is {size}")
+
+ response = sock.recv(size).decode()
+ print(f"Response: {response}")
+
+ request = {
+ "type": MESSAGE,
+ "data": "exit",
+ "user": "andrew"
+ }
+ send_message(sock, json.dumps(request).encode())
+ print(time() - t1)
+
- sock.sendall("exit".encode())
+if __name__ == '__main__':
+ main() \ No newline at end of file