使用 Socket 从浏览器读取请求后如何发送响应? (我正在使用 SwiftSocket)
Posted
技术标签:
【中文标题】使用 Socket 从浏览器读取请求后如何发送响应? (我正在使用 SwiftSocket)【英文标题】:How to send response after reading request from browser with Socket ? (I'm using SwiftSocket) 【发布时间】:2020-05-07 03:33:38 【问题描述】:我是 ios 网络的新手,所以不太了解所有概念,我正在制作一个允许在设备上的浏览器上显示数据的应用程序,
为此,我正在创建一个套接字端口并使用 SwiftSocket
库
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()
我认为下面的函数selfserver()
会初始化服务器并等待客户端连接
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)
当客户端尝试连接时,将调用以下函数senderclient(senderclient: TCPClient)
在响应中,我发送了index.html
文件,该文件保存在htmlfileURL
中,键入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)
我的问题是我得到了所有请求头,过滤后我还得到了请求头需要的 filename
和 content-type
,但我不知道之后如何发送这些文件在响应中接收和读取请求头..
如上图所示
在控制台区域,您可以看到我收到了styles.afcc5f0641cf44266b1b.css
文件的请求...我只是不知道在请求时如何将该文件发送到浏览器(我有文件的完整路径)
谢谢
【问题讨论】:
【参考方案1】:你创建的 TCPServer 实例,它实际上只存在于 selfserver 函数中。一旦 selfserver 函数返回,它就不再存在了!
专注于这样一个事实,即在运行 startconnection() 时,没有运行 TCPServer 实例,这意味着它没有响应。第一步,从
返回它的实例selfserver()->TCPsever ... return server
并将结果分配给 View 实例中的某些属性以延长其寿命
【讨论】:
那么我能做什么???....看到我在index.html
中添加了5个参考文件所以当我发送index.html
时startconnection()
中的开关循环正在运行5次,但我不明白如何在阅读我在startconnection
的开关循环中得到的响应后发送相关文件......你能解释一下这个概念吗,我没有得到任何简短的教程.....
专注于这样一个事实,即在运行 startconnection() 时,没有运行 TCPServer 实例,这意味着它没有响应......作为第一步,从 selfserver() 返回它的实例- >TCPsever ... return server 并将结果分配给 View 实例中的某个属性以延长其寿命
您能否详细说明一下这个 TCP 客户端/服务器概念,因为我在这方面遇到了很多困难,因为我刚刚开始 iOS 开发,而且我是这个套接字区域的新手......跨度>
【参考方案2】:
注意:- 我仍在寻找对每个人都非常有用的正确答案,因为 Swift
中的 Socket
是一个很难实现的概念
//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!
实现上述代码后,我可以获取所有请求标头并发送响应 但是只剩下一个问题了:(见下面的截图)
现在,正如您在图片中看到的那样,我能够读取所有响应标头,并且我也在发送请求的文件 但是问题(因为循环或者我不知道是什么)是我发送的响应文件将进入下一个请求而不是当前请求标头
例如:
它在第一个请求的文件中显示空数据,而我为第一个 styles.afcc5f0641cf44266b1b.css
发送的数据/文件将进入 runtime.26209474bfa8dc87a77c.js
的下一个(第二个)请求标头中,由于这种不规则性,我的最后一个文件favicon.ico
甚至没有被发送
【讨论】:
以上是关于使用 Socket 从浏览器读取请求后如何发送响应? (我正在使用 SwiftSocket)的主要内容,如果未能解决你的问题,请参考以下文章