-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.go
146 lines (130 loc) · 3.47 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package main
import (
"bufio"
"fmt"
"io"
"net"
"strconv"
"sync"
)
const maxSessions = 100
type session struct {
receiver net.Conn
sender net.Conn
mux sync.Mutex
readyChan chan struct{} // Channel to signal readiness
isReceiverReady bool // Tracks receiver readiness
}
var sessions [maxSessions]session
func main() {
listener, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Printf("Error starting server: %v\n", err)
return
}
defer listener.Close()
fmt.Println("Server listening on port 8080...")
for {
conn, err := listener.Accept()
if err != nil {
fmt.Printf("Error accepting connection: %v\n", err)
continue
}
go handleClient(conn)
}
}
func handleClient(conn net.Conn) {
defer conn.Close()
reader := bufio.NewReader(conn)
// Identify client type
clientType, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Error reading client type: %v\n", err)
return
}
clientType = clientType[:len(clientType)-1]
switch clientType {
case "RECEIVER":
handleReceiver(conn)
case "SENDER":
handleSender(conn, reader)
default:
fmt.Printf("Unknown client type: %s\n", clientType)
}
}
func handleReceiver(conn net.Conn) {
for i := 0; i < maxSessions; i++ {
session := &sessions[i]
session.mux.Lock()
if session.receiver == nil {
session.receiver = conn
session.readyChan = make(chan struct{}, 1)
session.isReceiverReady = true
session.mux.Unlock()
sessionID := strconv.Itoa(i)
fmt.Fprintf(conn, "%s\n", sessionID)
fmt.Printf("Receiver connected. Session ID: %s\n", sessionID)
select {} // Block until sender finishes
}
session.mux.Unlock()
}
fmt.Fprintln(conn, "Server full")
}
func handleSender(conn net.Conn, reader *bufio.Reader) {
sessionIDStr, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Error reading session ID: %v\n", err)
return
}
sessionID, err := strconv.Atoi(sessionIDStr[:len(sessionIDStr)-1])
if err != nil || sessionID < 0 || sessionID >= maxSessions {
fmt.Fprintln(conn, "Invalid session ID")
fmt.Printf("Invalid session ID: %s\n", sessionIDStr)
return
}
session := &sessions[sessionID]
session.mux.Lock()
if session.receiver == nil || !session.isReceiverReady {
session.mux.Unlock()
fmt.Fprintln(conn, "No receiver connected")
fmt.Printf("No receiver connected for Session ID: %d\n", sessionID)
return
}
session.sender = conn
session.mux.Unlock()
// Notify the sender that the receiver is ready
session.readyChan <- struct{}{}
close(session.readyChan) // Ensure the channel is closed after sending
fmt.Fprintln(conn, "READY")
fmt.Printf("Sender connected. Session ID: %d. Starting relay...\n", sessionID)
buffer := make([]byte, 4096)
for {
n, err := conn.Read(buffer)
if n > 0 {
session.mux.Lock()
_, writeErr := session.receiver.Write(buffer[:n])
session.mux.Unlock()
if writeErr != nil {
fmt.Printf("Error relaying data to receiver (ID: %d): %v\n", sessionID, writeErr)
break
}
fmt.Printf("Relayed %d bytes to receiver (ID: %d).\n", n, sessionID)
}
if err == io.EOF {
fmt.Printf("Sender finished sending data. (ID: %d)\n", sessionID)
break
}
if err != nil {
fmt.Printf("Error reading from sender (ID: %d): %v\n", sessionID, err)
break
}
}
// Clean up session
session.mux.Lock()
session.receiver.Close()
session.receiver = nil
session.sender = nil
session.isReceiverReady = false
session.mux.Unlock()
fmt.Printf("Relay complete for Session ID: %d.\n", sessionID)
}