-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsockets.clj
90 lines (81 loc) · 2.88 KB
/
sockets.clj
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
(ns triangulum.sockets
"Provides functionality for creating and managing client and server
sockets. It includes functions for opening and checking socket
connections, sending messages to the server, and starting/stopping
socket servers with custom request handlers. This namespace enables
communication between distributed systems and allows you to
implement networked applications."
(:import (java.io BufferedReader)
(java.net Socket ServerSocket))
(:require [clojure.java.io :as io]
[clojure.string :as s]
[triangulum.logging :refer [log log-str]]))
;;=================================
;; Client Socket
;;=================================
(defn socket-open?
"Checks if the socket at host/port is open."
[host port]
(try
(with-open [_ (Socket. host port)]
true)
(catch java.net.ConnectException _
false)))
(defn send-to-server!
"Attempts to send socket message. Returns :success if successful."
[host port message]
(try
(with-open [socket (Socket. host port)]
(doto (io/writer socket)
(.write (-> message
(s/trim-newline)
(str "\n")))
(.flush))
(.shutdownOutput socket))
:success
(catch java.net.ConnectException _
(log-str "Connection to " host ":" port "failed"))))
;;=================================
;; Server Socket
;;=================================
(defonce ^:private global-server-thread (atom nil))
(defonce ^:private global-server-socket (atom nil))
(defn- read-socket! [^Socket socket]
(.readLine ^BufferedReader (io/reader socket)))
(defn- accept-connections! [^ServerSocket server-socket handler]
(while @global-server-thread
(try
(let [socket (.accept server-socket)]
(try
(->> (read-socket! socket)
(handler))
(catch Exception e
(log-str "Server error: " e))
(finally (.close socket))))
(catch Exception _))))
(defn stop-socket-server!
"Stops the socket server at port with handler."
[]
(if @global-server-thread
(do
(reset! global-server-thread nil)
(when @global-server-socket
(.close ^ServerSocket @global-server-socket)
(reset! global-server-socket nil))
(log "Server stopped."))
(log "Server is not running.")))
(defn start-socket-server!
"Starts a socket server at port with handler."
[port handler]
(log "Starting socket server.")
(if @global-server-thread
(log "Server is already running.")
(reset! global-server-thread
(future
(try
(with-open [server-socket (ServerSocket. port)]
(reset! global-server-socket server-socket)
(accept-connections! server-socket handler))
(catch Exception e
(log-str "Error creating server socket: " e)
(stop-socket-server!)))))))