I am new to this networking in iOS so doesn't know all the concepts so well and I'm making an app which allows to show data on browser which is on device,
For that I'm creating a socket-port and using SwiftSocket
library
override func viewDidLoad() {
super.viewDidLoad()
let ip = String(getAddress(for: .wifi)!)
self.host = ip
print("Getting IP address of wifi\n\(self.host)\n")
self.selfserver()
}
I think following function selfserver()
initialises the server and wait for the client to connect
func selfserver()
{
let server = TCPServer(address: self.host, port: Int32(port))
switch server.listen() {
case .success:
while true {
if let client2 = server.accept() {
print("CLIENT ACCEPTED ....")
self.startconnection(senderclient: client2)
} else {
print("accept error")
}
}
case .failure(let error):
print(error)
}
}
When client will try to connect following function senderclient(senderclient: TCPClient)
will be called
and in the response I'm sending index.html
file which is saved in htmlfileURL
key in Userdefaults
func startconnection(senderclient: TCPClient) {
print("CLIENT ADD\n\(senderclient.address)\n")
let filePath = UserDefaults.standard.url(forKey: "htmlfileURL")
// Converting `index.html` in bytes to send
var bytes = [UInt8]()
if let data = NSData(contentsOfFile: filePath!.path) {
var buffer = [UInt8](repeating: 0, count: data.length)
data.getBytes(&buffer, length: data.length)
bytes = buffer
}
senderclient.send(string: "HTTP/1.1 200 OK\n" +
"Content-Length: \(bytes.count)\n" +
"Connection: close\n" +
"Content-Type: text/html\n" +
"\n")
switch senderclient.send(data: bytes) {
case .success:
let data = senderclient.read(1024*10)
if let d = data {
if let str = String(bytes: d, encoding: .utf8) {
print("STR\n\(str)\n")
// If I'm not wrong Here I should get the response
}
}
case .failure(let erro):
print(erro)
}
}
My problem is I am getting all request headers and after filtering I am also getting which filename
and content-type
the request header requires but I don't know how to send those file after receiving and reading the request header in reponse ..
As you can see in the above screenshot
In console area , you can see I'm getting a request of styles.afcc5f0641cf44266b1b.css
file...I just don't know how to send that file to the browser when it requests(I have full path of the file)
Thank You
NOTE:- I'm Still Searching for the Right answer which can be very useful to everyone as Socket
in Swift
is quite difficult concept to implement
//Iniiating Two variable which are initially empty to check if the loop is running first time
var loopablestring = String()
var loopableExtension = String()
//which was necessary here because otherwise only 'index.html' file will be sent in response to every request header
//MARK:- Start connection with Client Socket Function
func startconnection(senderclient: TCPClient) {
let filePath = Bundle.main.resourceURL
var FilePath = String()
var FileBytes = [Byte]()
var ContType = String()
//Initially this code will be called
if self.loopablestring == "" {
FilePath = filePath!.appendingPathComponent("index.html").path
FileBytes = self.getBytesFromFile(fromPath: FilePath)
self.loopableExtension = "html"
ContType = self.getMimeType(file: self.loopableExtension)
} else {
FilePath = filePath!.appendingPathComponent(loopablestring).path
FileBytes = self.getBytesFromFile(fromPath: FilePath)
ContType = self.getMimeType(file: self.loopableExtension)
}
//sending requested file(if any or sending 'index.html')
senderclient.send(string: "HTTP/1.1 200 OK\n" +
"Content-Length: \(FileBytes.count)\n" +
"Connection: close\n" +
"Content-Type: \(ContType)\n" +
"\n")
print("Sending File Of Which Content-Type\t\(ContType)\n And Path\t\(FilePath)\nAnd Pure File Name\t\(loopablestring)\nWith Extension\t\(loopableExtension)\n")
switch senderclient.send(data: FileBytes) {
case .success:
//print("SUCCESS")
if let responseBytes = senderclient.read(1024*10) {
let responseString = String(bytes: responseBytes, encoding: .utf8)!
print("\nRespons String which contains Headers\n\(responseString)\n\n")
let HeaderLines = responseString.components(separatedBy: .newlines)[0]
let separator = HeaderLines.components(separatedBy: .whitespaces)[1]
//print("Only first line of the Header\n\(HeaderLines)\n\n")
if separator != "/" {
//If we don't get Empty or nil value in request header then this code will run
let purefilename = separator.components(separatedBy: "/")[1]
//print("Pure File Name filtered from Header's First Line \n\(purefilename)\n")
print("ALLOCATED FILE \n\(purefilename)\n")
//giving that two variable values so in next loop's it won't go in `if self.loopablestring == ""` condition
self.loopablestring = purefilename
self.loopableExtension = self.getMimeType(file: separator)
//giving that two variable values so in next loop's it won't go in `if self.loopablestring == ""` condition
} else {
print("CAME HERE to be closed")
}
}
case .failure(let error):
print("FAILED because of \(error)")
}
print(" \t\t AFTER THE LOOP \n\n\n")
senderclient.close()
}
//To return Content Type to Browser (In response Header)
func getContentType(filename: String) -> String {
do {
if filename == "js" {
return "application/javascript"
} else if filename == "html" {
return "text/html"
} else if filename == "css" {
return "text/css"
} else if filename == "ico" || filename == "png" || filename == "PNG" || filename == "jpg" || filename == "JPG" || filename == "jpeg" || filename == "JPEG" {
return "image/png"
} else {
return "text/html"
}
} catch {
print("Something is Wrong!!")
}
}
//TO Get Extension without (.)DOT
func getMimeType(file: String) -> String {
let ext = file.components(separatedBy: ".")
//print("all extensions\n\(ext)\n")
return ext.last!
}
After implementing above code I'm able to get all the Request Headers and send the Response But there is only one issue left :(See the below Screenshot)
Now, as you can see in the image that I'm able to read all the response header and I'm sending the requested files too But issue (because of loop or I don't know what) is the response file I send is going in the next request instead of the current request header
ex:
It shows null data in the first requested file and the data/file I'm sending for first styles.afcc5f0641cf44266b1b.css
is going in the next(second) requested header of runtime.26209474bfa8dc87a77c.js
and because of this irregularity, my last file favicon.ico
is not even being sent
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With