diff options
| -rw-r--r-- | server/main.go | 76 | ||||
| -rw-r--r-- | tester.py | 79 |
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) } } } @@ -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 |