Swift的套接字服务器示例 [英] Socket Server Example with Swift

查看:74
本文介绍了Swift的套接字服务器示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图举一个简单的套接字服务器为例.

I tried to make an example of simple socket server.

构建并成功运行.但是它不能很好地工作.

Build and run successfully. However it doesn't work well.

客户端无法连接到该服务器.

Client couldn't connect to this server.

如何解决这个问题?我需要您的帮助,谢谢.

How to solve this problem? I need your help, thanks.

import Foundation

let BUFF_SIZE = 1024

func initStruct<S>() -> S {
    let struct_pointer = UnsafePointer<S>.alloc(1)
    let struct_memory = struct_pointer.memory
    struct_pointer.destroy()
    return struct_memory
}

func sockaddr_cast(p: ConstUnsafePointer<sockaddr_in>) -> UnsafePointer<sockaddr> {
    return UnsafePointer<sockaddr>(p)
}

func socklen_t_cast(p: UnsafePointer<Int>) -> UnsafePointer<socklen_t> {
    return UnsafePointer<socklen_t>(p)
}

var server_socket: Int32
var client_socket: Int32
var server_addr_size: Int
var client_addr_size: Int

var server_addr: sockaddr_in = initStruct()
var client_addr: sockaddr_in = initStruct()

var buff_rcv: Array<CChar> = []
var buff_snd: String

server_socket = socket(PF_INET, SOCK_STREAM, 0);

if server_socket == -1
{
    println("[Fail] Create Server Socket")
    exit(1)
}
else
{
    println("[Success] Created Server Socket")
}

server_addr_size = sizeof(server_addr.dynamicType)
memset(&server_addr, 0, UInt(server_addr_size));

server_addr.sin_family = sa_family_t(AF_INET)
server_addr.sin_port = 4000
server_addr.sin_addr.s_addr = UInt32(0x00000000)    // INADDR_ANY = (u_int32_t)0x00000000 ----- <netinet/in.h>

let bind_server = bind(server_socket, sockaddr_cast(&server_addr), socklen_t(server_addr_size))

if bind_server == -1
{
    println("[Fail] Bind Port");
    exit(1);
}
else
{
    println("[Success] Binded Port");
}

if listen(server_socket, 5) == -1
{
    println("[Fail] Listen");
    exit(1);
}
else
{
    println("[Success] Listening : \(server_addr.sin_port) Port ...");
}

var n = 0

while n < 1
{
    client_addr_size = sizeof(client_addr.dynamicType)
    client_socket = accept(server_socket, sockaddr_cast(&client_addr), socklen_t_cast(&client_addr_size))

    if client_socket == -1
    {
        println("[Fail] Accept Client Connection");
        exit(1);
    }
    else
    {
        println("[Success] Accepted Client : \(inet_ntoa(client_addr.sin_addr)) : \(client_addr.sin_port)");
    }

    read(client_socket, &buff_rcv, UInt(BUFF_SIZE))

    println("[Success] Received : \(buff_rcv)")

    buff_snd = "\(strlen(buff_rcv)) : \(buff_rcv)"

    write(client_socket, &buff_snd, strlen(buff_snd) + 1)

    close(client_socket)
}

推荐答案

套接字地址中的端口号必须为大端字节序:

The port number in the socket address must be in big-endian byte order:

server_addr.sin_port = UInt16(4000).bigEndian

因此您的程序实际上在端口40975(十六进制0xA00F)上侦听,而不是 在端口4000(十六进制0x0FA0)上.

So your program actually listens on port 40975 (hex 0xA00F) and not on port 4000 (hex 0x0FA0).

另一个问题在这里:

var buff_rcv: Array<CChar> = []
// ...
read(client_socket, &buff_rcv, UInt(BUFF_SIZE))

您的缓冲区是一个 empty 数组,但是recv()希望缓冲区的大小为BUFF_SIZE. 该行为是未定义的.要获得所需大小的缓冲区,请使用

Your buffer is an empty array, but recv() expects a buffer of size BUFF_SIZE. The behaviour is undefined. To get a buffer of the required size, use

var buff_rcv = [CChar](count:BUFF_SIZE, repeatedValue:0)
// ...
read(client_socket, &buff_rcv, UInt(buff_rcv.count))

备注:在这里,您将Int的地址转换为socklen_t的地址 并将其传递给accept()函数:

Remark: Here you cast the address of an Int to the address of an socklen_t and pass that to the accept() function:

client_socket = accept(server_socket, sockaddr_cast(&client_addr), socklen_t_cast(&client_addr_size))

那不安全.如果Intsocklen_t具有不同的大小,则行为 将是不确定的.您应该声明server_addr_sizeclient_addr_size 作为socklen_t并删除socklen_t_cast()函数:

That is not safe. If Int and socklen_t have different sizes then the behaviour will be undefined. You should declare server_addr_size and client_addr_size as socklen_t and remove the socklen_t_cast() function:

client_socket = accept(server_socket, sockaddr_cast(&client_addr), &client_addr_size)

这篇关于Swift的套接字服务器示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆