G O*_*ira 3 ip tcp swift server
我一直试图快速编写一个简单的TCP / IP服务器,但是我无法提出解决方案。我已经尝试过在这里和整个网络中进行搜索,但是找不到与我正在使用的最新Swift版本兼容的内容:
Apple Swift版本2.1(swiftlang-700.1.101.6 clang-700.1.76)
目标:x86_64-apple-darwin14.5.0
操作系统:
Mac OS X 10.10.5 Yosemitte
下面的代码已经基于此代码完成:带Swift的Socket Server示例
import Foundation
var sock_fd: Int32
var server_addr_size: Int
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if sock_fd == -1 {
print("Failure: creating socket")
exit(EXIT_FAILURE)
}
server_addr_size = sizeof(sockaddr_in)
var server_addr = NSMutableData(length: server_addr_size)!
memset(UnsafeMutablePointer<Void>(server_addr.mutableBytes), 0, server_addr_size)
var addr = UnsafeMutablePointer<sockaddr_in>(server_addr.mutableBytes)
addr.memory.sin_len = __uint8_t(server_addr_size)
addr.memory.sin_family = sa_family_t(AF_INET) // chooses IPv4
addr.memory.sin_port = 12321 // chooses the port
let bind_server = bind(sock_fd, UnsafePointer<sockaddr>(server_addr.mutableBytes), socklen_t(server_addr_size))
if bind_server == -1 {
print("Failure: binding port")
exit(EXIT_FAILURE)
}
if listen(sock_fd, 5) == -1 {
print("Failure: listening")
exit(EXIT_FAILURE)
}
var client_addr = NSMutableData(length: server_addr_size)!
memset(UnsafeMutablePointer<Void>(client_addr.mutableBytes), 0, server_addr_size)
let client_fd = accept(sock_fd, UnsafeMutablePointer<sockaddr>(client_addr.mutableBytes), UnsafeMutablePointer<socklen_t>(bitPattern: server_addr_size))
if client_fd == -1 {
print("Failure: accepting connection")
exit(EXIT_FAILURE);
}
Run Code Online (Sandbox Code Playgroud)
从上述代码给出的输出中可以看出,对accept的调用失败了:
失败:接受连接
程序以退出代码结束:1
除了帮助修复代码外,我还想知道如何读写连接。
谢谢,
G·奥利维拉
在
UnsafeMutablePointer<socklen_t>(bitPattern: server_addr_size)
Run Code Online (Sandbox Code Playgroud)
您正在将整数变量重新解释为指针。这没有任何意义,并且在运行时崩溃,因为变量的内容未指向有效内存。该accept()函数在这里期望
一个类型的变量的地址socklen_t。
还有其他问题,例如,套接字地址中的端口号必须为大端字节顺序:
server_addr.sin_port = UInt16(12321).bigEndian // chooses the port
Run Code Online (Sandbox Code Playgroud)
否则,您的程序将侦听端口8496而不是12321。
使用NSMutableData不是必需的,从Swift 1.2开始,您可以使用以下命令创建一个sockaddr_in将所有元素设置为零的结构:
var server_addr = sockaddr_in()
Run Code Online (Sandbox Code Playgroud)
然后withUnsafePointer()可以用来获取该结构的地址。
如果系统调用失败,则将全局变量errno设置为指示错误原因的非零值。perror()可用于打印与相对应的错误消息errno。
您可能需要设置SO_REUSEADDR套接字选项,以避免在绑定套接字时出现“地址已在使用中”错误,请参见
SO_REUSEADDR的使用?或
套接字选项SO_REUSEADDR和SO_REUSEPORT,它们有何不同?它们在所有主要操作系统上的含义都一样吗?想要查询更多的信息。
这是代码的清理版本,可以在我的测试中正常工作:
let sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if sock_fd == -1 {
perror("Failure: creating socket")
exit(EXIT_FAILURE)
}
var sock_opt_on = Int32(1)
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &sock_opt_on, socklen_t(sizeofValue(sock_opt_on)))
var server_addr = sockaddr_in()
let server_addr_size = socklen_t(sizeofValue(server_addr))
server_addr.sin_len = UInt8(server_addr_size)
server_addr.sin_family = sa_family_t(AF_INET) // chooses IPv4
server_addr.sin_port = UInt16(12321).bigEndian // chooses the port
let bind_server = withUnsafePointer(&server_addr) {
bind(sock_fd, UnsafePointer($0), server_addr_size)
}
if bind_server == -1 {
perror("Failure: binding port")
exit(EXIT_FAILURE)
}
if listen(sock_fd, 5) == -1 {
perror("Failure: listening")
exit(EXIT_FAILURE)
}
var client_addr = sockaddr_storage()
var client_addr_len = socklen_t(sizeofValue(client_addr))
let client_fd = withUnsafeMutablePointer(&client_addr) {
accept(sock_fd, UnsafeMutablePointer($0), &client_addr_len)
}
if client_fd == -1 {
perror("Failure: accepting connection")
exit(EXIT_FAILURE);
}
print("connection accepted")
Run Code Online (Sandbox Code Playgroud)
该read()和write()系统调用,然后用于读取和写入到接受的套接字。
只是Swift 4的一点更新。
import Foundation
let sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if sock_fd == -1 {
perror("Failure: creating socket")
exit(EXIT_FAILURE)
}
var sock_opt_on = Int32(1)
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &sock_opt_on, socklen_t(MemoryLayout.size(ofValue: sock_opt_on)))
var server_addr = sockaddr_in()
let server_addr_size = socklen_t(MemoryLayout.size(ofValue: server_addr))
server_addr.sin_len = UInt8(server_addr_size)
server_addr.sin_family = sa_family_t(AF_INET) // chooses IPv4
server_addr.sin_port = UInt16(12321).bigEndian // chooses the port
let bind_server = withUnsafePointer(to: &server_addr) {
bind(sock_fd, UnsafeRawPointer($0).assumingMemoryBound(to: sockaddr.self), server_addr_size)
}
if bind_server == -1 {
perror("Failure: binding port")
exit(EXIT_FAILURE)
}
if listen(sock_fd, 5) == -1 {
perror("Failure: listening")
exit(EXIT_FAILURE)
}
var client_addr = sockaddr_storage()
var client_addr_len = socklen_t(MemoryLayout.size(ofValue: client_addr))
let client_fd = withUnsafeMutablePointer(to: &client_addr) {
accept(sock_fd, UnsafeMutableRawPointer($0).assumingMemoryBound(to: sockaddr.self), &client_addr_len)
}
if client_fd == -1 {
perror("Failure: accepting connection")
exit(EXIT_FAILURE);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6220 次 |
| 最近记录: |