sfml3.rb

Class: SFML::TcpSocket

Inherits:
Object
  • Object
show all
Defined in:
ext/network/tcp_socket.c,
ext/network/tcp_socket.c

Overview

A connection-oriented, reliable, byte-stream socket for TCP communication. Connect with #connect (or receive one already connected from TcpListener#accept), then send/receive raw bytes or Packet instances.

Instance Method Summary collapse

Constructor Details

#new ⇒ TcpSocket

Creates a new, unconnected TCP socket.



61
62
63
# File 'ext/network/tcp_socket.c', line 61

static VALUE TcpSocket_initialize(VALUE self) {
    return self;
}

Instance Method Details

#blocking=(value) ⇒ Boolean

Enables or disables blocking mode according to value.

Returns:

  • (Boolean) —

    value



82
83
84
85
# File 'ext/network/tcp_socket.c', line 82

static VALUE TcpSocket_set_blocking(VALUE self, VALUE rb_value) {
    sfTcpSocket_setBlocking(Get_TcpSocket_Struct(self), RTEST(rb_value));
    return rb_value;
}

#blocking? ⇒ Boolean

Returns true if the socket is in blocking mode.

Returns:

  • (Boolean)

Returns:

  • (Boolean)


71
72
73
# File 'ext/network/tcp_socket.c', line 71

static VALUE TcpSocket_blocking(VALUE self) {
    return BOOL2RB(sfTcpSocket_isBlocking(Get_TcpSocket_Struct(self)));
}

#connect(address, port, timeout = Time.zero) ⇒ Symbol

Connects to a remote peer, blocking (unless #blocking? is false) until connected or timeout elapses.

Returns:

  • (Symbol)

Returns:

  • (Symbol) —

    a SocketStatus name, :done on success



127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'ext/network/tcp_socket.c', line 127

static VALUE TcpSocket_connect(int argc, VALUE* argv, VALUE self) {
    VALUE rb_address, rb_port, rb_timeout;
    sfTime timeout = sfTime_Zero;

    rb_scan_args(argc, argv, "21", &rb_address, &rb_port, &rb_timeout);

    if (!NIL_P(rb_timeout)) {
        timeout = time_from_rb(rb_timeout);
    }

    return ID2SYM(rb_intern(socket_status_name(sfTcpSocket_connect(
        Get_TcpSocket_Struct(self), ip_address_from_rb(rb_address, sfIpAddress_None),
        (unsigned short)NUM2INT(rb_port), timeout))));
}

#disconnect ⇒ self

Closes the connection.

Returns:

  • (self)

Returns:

  • (self)


148
149
150
151
# File 'ext/network/tcp_socket.c', line 148

static VALUE TcpSocket_disconnect(VALUE self) {
    sfTcpSocket_disconnect(Get_TcpSocket_Struct(self));
    return self;
}

#local_port ⇒ Integer

Returns the local port the socket is bound to.

Returns:

  • (Integer)

Returns:

  • (Integer) —

    the local port the socket is bound to, or 0 if it isn't connected



94
95
96
# File 'ext/network/tcp_socket.c', line 94

static VALUE TcpSocket_local_port(VALUE self) {
    return UINT2NUM(sfTcpSocket_getLocalPort(Get_TcpSocket_Struct(self)));
}

#receive(max_length = 1024) ⇒ Array, Symbol

Receive needs a maximum size up front because CSFML fills a caller buffer. Returns [data, status], where data is empty unless the status is :done.

Returns ].

Returns:

  • (Array, Symbol) —

    ]

Returns:

  • (Array(String, Symbol)) —

    the bytes received, and a SocketStatus name

Raises:

  • (ArgumentError) —

    if max_length isn't positive



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'ext/network/tcp_socket.c', line 204

static VALUE TcpSocket_receive(int argc, VALUE* argv, VALUE self) {
    VALUE rb_max_length;
    long max_length = 1024;
    char* buffer;
    size_t received = 0;
    sfSocketStatus status;
    VALUE rb_result;

    rb_scan_args(argc, argv, "01", &rb_max_length);

    if (!NIL_P(rb_max_length)) {
        max_length = NUM2LONG(rb_max_length);
    }

    if (max_length <= 0) {
        rb_raise(rb_eArgError, "maximum length must be positive");
    }

    buffer = malloc((size_t)max_length);

    if (buffer == NULL) {
        rb_raise(rb_eNoMemError, "failed to allocate receive buffer");
    }

    status = sfTcpSocket_receive(Get_TcpSocket_Struct(self), buffer, (size_t)max_length, &received);

    rb_result = rb_ary_new_capa(2);
    rb_ary_push(rb_result, rb_str_new(buffer, (long)received));
    rb_ary_push(rb_result, ID2SYM(rb_intern(socket_status_name(status))));

    free(buffer);

    return rb_result;
}

#receive_packet(packet) ⇒ Symbol

Fills packet (replacing its previous contents) with the next packet received.

Returns:

  • (Symbol)

Returns:

  • (Symbol) —

    a SocketStatus name, :done on success

Raises:

  • (TypeError) —

    if packet is not an SFML::Packet



265
266
267
268
269
270
271
272
# File 'ext/network/tcp_socket.c', line 265

static VALUE TcpSocket_receive_packet(VALUE self, VALUE rb_packet) {
    if (!rb_obj_is_kind_of(rb_packet, Get_Klass_Packet())) {
        rb_raise(rb_eTypeError, "expected an SFML::Packet");
    }

    return ID2SYM(rb_intern(socket_status_name(
        sfTcpSocket_receivePacket(Get_TcpSocket_Struct(self), Get_Packet_Struct(rb_packet)))));
}

#remote_address ⇒ IpAddress

Returns the address of the remote peer.

Returns:

Returns:

  • (IpAddress) —

    the address of the remote peer, or IpAddress::NONE if not connected



105
106
107
# File 'ext/network/tcp_socket.c', line 105

static VALUE TcpSocket_remote_address(VALUE self) {
    return ip_address_to_rb(sfTcpSocket_getRemoteAddress(Get_TcpSocket_Struct(self)));
}

#remote_port ⇒ Integer

Returns the port of the remote peer.

Returns:

  • (Integer)

Returns:

  • (Integer) —

    the port of the remote peer, or 0 if not connected



115
116
117
# File 'ext/network/tcp_socket.c', line 115

static VALUE TcpSocket_remote_port(VALUE self) {
    return UINT2NUM(sfTcpSocket_getRemotePort(Get_TcpSocket_Struct(self)));
}

#send(data) ⇒ Symbol

Sends the full contents of data, blocking (unless #blocking? is false) until it is all sent. Prefer #send_partial for non-blocking sockets, since this can return :not_ready having sent only part of the data with no way to know how much.

Returns:

  • (Symbol)

Returns:

  • (Symbol) —

    a SocketStatus name, :done on success



163
164
165
166
167
168
# File 'ext/network/tcp_socket.c', line 163

static VALUE TcpSocket_send(VALUE self, VALUE rb_data) {
    StringValue(rb_data);

    return ID2SYM(rb_intern(socket_status_name(sfTcpSocket_send(
        Get_TcpSocket_Struct(self), RSTRING_PTR(rb_data), (size_t)RSTRING_LEN(rb_data)))));
}

#send_packet(packet) ⇒ Symbol

Sends packet over the connection.

Returns:

  • (Symbol)

Returns:

  • (Symbol) —

    a SocketStatus name, :done on success

Raises:

  • (TypeError) —

    if packet is not an SFML::Packet



247
248
249
250
251
252
253
254
# File 'ext/network/tcp_socket.c', line 247

static VALUE TcpSocket_send_packet(VALUE self, VALUE rb_packet) {
    if (!rb_obj_is_kind_of(rb_packet, Get_Klass_Packet())) {
        rb_raise(rb_eTypeError, "expected an SFML::Packet");
    }

    return ID2SYM(rb_intern(socket_status_name(
        sfTcpSocket_sendPacket(Get_TcpSocket_Struct(self), Get_Packet_Struct(rb_packet)))));
}

#send_partial(data) ⇒ Array, Symbol

Like #send, but may send only part of data and reports how much.

Returns ].

Returns:

  • (Array, Symbol) —

    ]

Returns:

  • (Array(Integer, Symbol)) —

    the number of bytes actually sent, and a SocketStatus name



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'ext/network/tcp_socket.c', line 178

static VALUE TcpSocket_send_partial(VALUE self, VALUE rb_data) {
    size_t sent = 0;
    sfSocketStatus status;
    VALUE rb_result;

    StringValue(rb_data);

    status = sfTcpSocket_sendPartial(Get_TcpSocket_Struct(self), RSTRING_PTR(rb_data),
                                     (size_t)RSTRING_LEN(rb_data), &sent);

    rb_result = rb_ary_new_capa(2);
    rb_ary_push(rb_result, SIZET2NUM(sent));
    rb_ary_push(rb_result, ID2SYM(rb_intern(socket_status_name(status))));

    return rb_result;
}