Coder Social home page Coder Social logo

swiftsockets's Introduction

SwiftSockets

Swift3 Swift4 Mac OS X iOS Linux MIT Travis

A simple GCD based socket library for Swift.

SwiftSockets is kind of a demo on how to integrate Swift with raw C APIs. More for stealing Swift coding ideas than for actually using the code in a real world project. In most real world Swift apps you have access to Cocoa, use it. If you need a Swift networking toolset for the server side, consider: Noze.io.

It also comes with a great Echo daemon as a demo, it's always there if you need a chat.

Note: This is my first Swift project. Any suggestions on how to improve the code are welcome. I expect lots and lots :-)

Targets

The project includes three targets:

  • SwiftSockets

  • ARIEchoServer

  • ARIFetch

  • Updated for Swift 3.2/4.0 (aka Xcode 9.1), and for Swift 3 final too

  • Updated for Swift 0.2.2 (aka Xcode 7.3), aand for Swift 0.3-2016-05-31.

Note for Linux users: This compiles with the 2016-05-31-a snapshot via Swift Package Manager as well as with the Swift 2.2 release using the embedded makefiles. Make sure you install Grand Central Dispatch into your Swift installation. On Linux the included ARIEchoServer/ARIFetch apps do not build, but this one does and is embedded: SwiftyEchoDaemon.

SwiftSockets

A framework containing the socket classes and relevant extensions. It takes a bit of inspiration from the SOPE NGStreams library.

Server Sample:

let socket = PassiveSocket<sockaddr_in>(address: sockaddr_in(port: 4242))!
  .listen(queue: DispatchQueue.global(), backlog: 5) {
    print("Wait, someone is attempting to talk to me!")
    $0.close()
    print("All good, go ahead!")
  }

Client Sample:

let socket = ActiveSocket<sockaddr_in>()!
  .onRead { sock, _ in
    let (count, block, errno) = sock.read() // $0 for sock doesn't work anymore?
    guard count > 0 else {
      print("EOF, or great error handling \(errno).")
      return
    }
    print("Answer to ring,ring is: \(count) bytes: \(block)")
  }
  .connect("127.0.0.1:80") { socket in
    socket.write("Ring, ring!\r\n")
  }

Using SwiftSockets with Swift Package Manager

To use SwiftSockets in your SPM project, just add it as a dependency in your Package.swift file, like so:

import PackageDescription

let package = Package(
  name:         "SwiftyEcho",
  targets:      [],
  dependencies: [
    .Package(url: "https://github.com/AlwaysRightInstitute/SwiftSockets.git",
             majorVersion: 0, minor: 1
    )
  ]
)

ARIEchoServer / SwiftyEchoDaemon

There is the ARIEchoServer for Xcode and SwiftEchoDaemon for Package Manager installs. Your choize, both are equally awezome.

ARIEchoServer is a Cocoa app. Compile it, run it, then connect to it in the Terminal.app via telnet 1337.

The bezt Echo daemon ever written in Swift - SPM version. This is a demo on how to write a SwiftSockets server using the Swift Package Manager, on Linux or OSX. It also works w/o SPM if SwiftSockets has been built via Makefiles.

Great echo server. Compile it via make, run it via make run, then connect to it in the Terminal.app via telnet 1337.

ARIFetch

Connects a socket to some end point, sends an HTTP/1.0 GET request with some awesome headers, then shows the results the server sends. Cocoa app.

Why HTTP/1.0? Avoids redirects on www.apple.com :-)

Goals

  • Max line length: 80 characters
  • Great error handling
    • PS style great error handling
    • print() error handling
    • Swift 2 try/throw/catch
      • Real error handling
  • Twisted (no blocking reads or writes)
    • Async reads and writes
      • Never block on reads
      • Never block on listen
    • Async connect()
  • Support all types of Unix sockets & addresses
    • IPv4
    • IPv6 (I guess this should work too)
    • Unix domain sockets
    • Datagram sockets
  • No NS'ism
  • Use as many language features Swift provides
    • Generics
      • Generic function
      • typealias
    • Closures
      • weak self
      • trailing closures
      • implicit parameters
    • Unowned
    • Extensions on structs
    • Extensions to organize classes
    • Protocols on structs
    • Swift 2 protocol extensions
    • Tuples, with labels
    • Trailing closures
    • @Lazy
    • Pure Swift weak delegates via @class
    • Optionals
    • Convenience initializers
    • Failable initializers
    • Class variables on structs
    • CConstPointer, CConstVoidPointer
      • withCString {}
    • UnsafePointer
    • sizeof()
    • strideof()
    • Standard Protocols
      • Printable
      • BooleanType (aka LogicValue[1.x] aka Boolean[3.x])
      • OutputStreamType / Swift 3 OutputStream
      • Equatable
        • Equatable on Enums with Associated Values
      • Hashable
      • SequenceType (GeneratorOf)
        • Swift 3 Sequence (Iterator)
      • Literal Convertibles
        • StringLiteralConvertible
        • IntegerLiteralConvertible
    • Left shift AND right shift
    • Enums on steroids
    • Dynamic type system, reflection
    • Operator overloading
    • UCS-4 identifiers (๐Ÿ”๐Ÿ”๐Ÿ”)
    • RTF source code with images and code sections in different fonts
    • Nested classes/types
    • Patterns
      • Use wildcard pattern to ignore value
    • Literal Convertibles
    • @autoclosure
    • unsafeBitCast (was reinterpretCast)
    • final
    • Nil coalescing operator
    • dynamic
    • Swift 2
      • availability
      • guard
      • defer
      • C function pointers
      • debugPrint
      • lowercaseString
    • #if os(Linux)
    • #if swift(>=2.2)
  • Swift Package Manager
    • GNUmakefile support
    • #if SWIFT_PACKAGE
  • Linux support
  • Swift 3 2016-03-16

Why?!

This is an experiment to get acquainted with Swift. To check whether something real can be implemented in 'pure' Swift. Meaning, without using any Objective-C Cocoa classes (no NS'ism). Or in other words: Can you use Swift without writing all the 'real' code in wrapped Objective-C? :-)

Contact

@helje5 | [email protected]

swiftsockets's People

Contributors

bryant1410 avatar danappelxx avatar helje5 avatar izqui avatar tomerdmann avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swiftsockets's Issues

Weird init() of sockaddr_in taking the port first, then the address.

Our custom sockaddr_in() initializer currently takes the port first, like this:

let address = sockaddr_in(port: 80, address: ...)

Would be more natural to reverse this, like:

let address = sockaddr_in(address: "192.168.0.1", port: 80)

or maybe even:

let address = sockaddr_in("192.168.0.1:80")

Provide a non-blocking connect()

The current implementation blocks on connect(). Would be nice to have an asynchronous variant. Not sure GCD has a (scalable) solution for that builtin or whether we need to make the Unix socket non-blocking.

Without Foundation

Hi, I saw this project and it goes into the direction of what I look for, but you still use the Foundation Framework.
The question is: is this possible with the standard library and C libraries only? I search for that having the upcoming Linux compiler in mind because I was planning to build a server-side network application on Swift that would run on a Linux system. But for that there has to be a network library that is completely platform independent and rely on the existing standard libraries of that system.
Are you going to do that and/or do you see a way to do so?

ARIFetch Fails on String Conversion

When ARIFetch receives a full read-buffer (4096 bytes), it sometimes stops. This is because the read() might end within an UTF-8 sequence (the UTF-8 decoding will fail and the non-optional withCString will just abort).

Solution: I think we need to check the buffer some bytes backwards for an UTF-8 marker, and then concatenate the results until something valid is constructed.
Or for the demo, we just build one big byte buffer, and then log it.

Error 35 on socket.read()

Hi!

First of all thanks for your work, the library is super cool.

I have a problem with the library and it is that it randomly returns error 35 on socket.listen. The distribution of the errors seems to be arbitrary and the it happens like 1/3 of the times, I have also observed that when I'm debugging and putting breakpoints between connections, it doesn't happen. I also tried other queues different from the main queue, without success.

My current implementation is here.

I have no clue what could be the origin of the issue.

screen shot 2015-10-13 at 8 25 37 pm

CocoaPods?

Does it make sense to provide the ARISockets framework as a CocoaPod? Maybe, just for the heck of it.

Passing nil as a dispatch block fails on newest version of Xcode

The following lines of code don't build on the newest version of Xcode:

guard let asyncData = dispatch_data_create(buffer,bufsize, queue,nil) else {
    return false
}

with the following error:

ActiveSocket.swift:311:70: Nil is not compatible with expected argument type 'dispatch_block_t' (aka '@convention(block) () -> ()')

I'll submit a pull request which changes nil to {} (an empty block), which should work.

Support the new Swift package manager

I was wondering if there are any plans to support the new Swift package manager. I'd love to contribute to the effort, but wanted to check in with the team before putting together any PRs.

Crash with EXC_ARM_DA_ALIGN in iOS7 release version

Hello,

I use your lib in iOS app develop.
Before swift2.0, it works smoothly.
Now I use swift2.0 in Xcode 7, it can't work in iOS 7 release version(iOS 8+ is OK).
But in debug version, it also can work normaly.
The crash place looks like here:

public convenience init?(type: Int32 = SOCK_STREAM) {
let lfd = socket(T.domain, type, 0)
guard lfd != -1 else { return nil }

self.init(fd: FileDescriptor(lfd))      <---   looks like crash here..

}

I don't know how to do, Can you help me to fix it?

Xcode does not have an iOS framework target

This is not an issue for Cocoapods since it just builds the source files, but when the framework is built with Carthage (or just Xcode, really), there is no target to output an iOS framework.

Ideally, there would be the framework targets SwiftSockets-OSX and SwiftSockets-iOS, both with the same product name. This is a bit of annoying to do, so I'll do it for you! I just wanted to check in and ask if this is alright before I do.

By the way, we've been using SwiftSockets for Taylor for a couple weeks and haven't had any issues with it yet! Great job ๐Ÿ‘

Swift 3 support

Does this project support Swift 3 fully?

I'm currently upgrading our projects to swift 3 and started using this with the older versions of swift, but after upgrading I'm getting several failures on comilation of this pulled in as a Pod.

I've tried the standard cocoapods that's latest and another branch.

pod 'SwiftSockets', '~> 0.22.10'

pod 'SwiftSockets', :git => "https://github.com/AlwaysRightInstitute/SwiftSockets", :tag => '0.22.8'

Here's a few errors from the 0.22.8 branch.

/Users/nneuberger/ws/kiosk-ios-app/Pods/SwiftSockets/Sources/SwiftSockets/SocketAddress.swift:127:18: Value of type 'sockaddr_in' has no member 'dynamicType'

/Users/nneuberger/ws/kiosk-ios-app/Pods/SwiftSockets/Sources/SwiftSockets/SocketAddress.swift:127:18: Value of type 'sockaddr_in' has no member 'dynamicType'
/Users/nneuberger/ws/kiosk-ios-app/Pods/SwiftSockets/Sources/SwiftSockets/SocketAddress.swift:266:16: Value of type 'sockaddr_in6' has no member 'dynamicType'

/Users/nneuberger/ws/kiosk-ios-app/Pods/SwiftSockets/Sources/SwiftSockets/UnixUtils.swift:39:11: 'dispatch_source_t' is unavailable in Swift

There are several other errors as well.

Support Linux Swift

SwiftSockets doesn't use any Objective-C stuff and should run on Linux Swift. Make this work.

How do I print out a client's message on server side?

If I'm listening on port 8080, and I have a client (Active socket) write to the socket, how do I print from the serverside that message?

let socket = PassiveSocket<sockaddr_in>(address: sockaddr_in(port: 8080))!
.listen(dispatch_get_global_queue(0, 0), backlog: 5) {
print("Wait, someone is attempting to talk to me!")

            $0.close()
            print("All good, go ahead!")
    }
}

I think it would go somewhere in here, but I have no idea where to go from that.

thanks

Read can block if a read block has the same size as the buffer

Since we have no ioctl() we cannot determine the number of bytes available in the operating systems receive buffer.

    // LAME HACK around the missing ioctl().
    // This is going to block at least queue thread? if a buffer is received
    // which is exactly the size of the readBuffer
    // TBD: maybe we can use poll() on the descriptor to see if sth is waiting?
    // TBD: or make the socket itself unblocking
    if count == socket.readBufferSize {
      println("Got a full buffer, more data waiting? MIGHT BLOCK")
      socket.onRead?(socket) // recurse
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.