Skip to content

Commit 2bae624

Browse files
committed
Basic UDP Client
1 parent 3b40b4b commit 2bae624

File tree

6 files changed

+206
-4
lines changed

6 files changed

+206
-4
lines changed
Binary file not shown.
Binary file not shown.

UDPClient.xcodeproj/project.pbxproj

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
F6589E351C744EC600AB029C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F6589E331C744EC600AB029C /* Main.storyboard */; };
1313
F6589E371C744EC600AB029C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F6589E361C744EC600AB029C /* Assets.xcassets */; };
1414
F6589E3A1C744EC600AB029C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F6589E381C744EC600AB029C /* LaunchScreen.storyboard */; };
15+
F6589E431C74500600AB029C /* CocoaAsyncSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6589E421C74500600AB029C /* CocoaAsyncSocket.framework */; };
1516
/* End PBXBuildFile section */
1617

1718
/* Begin PBXFileReference section */
@@ -22,13 +23,15 @@
2223
F6589E361C744EC600AB029C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
2324
F6589E391C744EC600AB029C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
2425
F6589E3B1C744EC600AB029C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
26+
F6589E421C74500600AB029C /* CocoaAsyncSocket.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CocoaAsyncSocket.framework; path = Carthage/Build/iOS/CocoaAsyncSocket.framework; sourceTree = "<group>"; };
2527
/* End PBXFileReference section */
2628

2729
/* Begin PBXFrameworksBuildPhase section */
2830
F6589E291C744EC600AB029C /* Frameworks */ = {
2931
isa = PBXFrameworksBuildPhase;
3032
buildActionMask = 2147483647;
3133
files = (
34+
F6589E431C74500600AB029C /* CocoaAsyncSocket.framework in Frameworks */,
3235
);
3336
runOnlyForDeploymentPostprocessing = 0;
3437
};
@@ -38,6 +41,7 @@
3841
F6589E231C744EC600AB029C = {
3942
isa = PBXGroup;
4043
children = (
44+
F6589E421C74500600AB029C /* CocoaAsyncSocket.framework */,
4145
F6589E2E1C744EC600AB029C /* UDPClient */,
4246
F6589E2D1C744EC600AB029C /* Products */,
4347
);
@@ -74,6 +78,7 @@
7478
F6589E281C744EC600AB029C /* Sources */,
7579
F6589E291C744EC600AB029C /* Frameworks */,
7680
F6589E2A1C744EC600AB029C /* Resources */,
81+
F6589E411C744F4B00AB029C /* Carthage */,
7782
);
7883
buildRules = (
7984
);
@@ -131,6 +136,24 @@
131136
};
132137
/* End PBXResourcesBuildPhase section */
133138

139+
/* Begin PBXShellScriptBuildPhase section */
140+
F6589E411C744F4B00AB029C /* Carthage */ = {
141+
isa = PBXShellScriptBuildPhase;
142+
buildActionMask = 2147483647;
143+
files = (
144+
);
145+
inputPaths = (
146+
"$(SRCROOT)/Carthage/Build/iOS/CocoaAsyncSocket.framework",
147+
);
148+
name = Carthage;
149+
outputPaths = (
150+
);
151+
runOnlyForDeploymentPostprocessing = 0;
152+
shellPath = /bin/sh;
153+
shellScript = "/usr/local/bin/carthage copy-frameworks";
154+
};
155+
/* End PBXShellScriptBuildPhase section */
156+
134157
/* Begin PBXSourcesBuildPhase section */
135158
F6589E281C744EC600AB029C /* Sources */ = {
136159
isa = PBXSourcesBuildPhase;
@@ -248,6 +271,10 @@
248271
isa = XCBuildConfiguration;
249272
buildSettings = {
250273
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
274+
FRAMEWORK_SEARCH_PATHS = (
275+
"$(inherited)",
276+
"$(PROJECT_DIR)/Carthage/Build/iOS",
277+
);
251278
INFOPLIST_FILE = UDPClient/Info.plist;
252279
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
253280
PRODUCT_BUNDLE_IDENTIFIER = com.stansidel.UDPClient;
@@ -259,6 +286,10 @@
259286
isa = XCBuildConfiguration;
260287
buildSettings = {
261288
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
289+
FRAMEWORK_SEARCH_PATHS = (
290+
"$(inherited)",
291+
"$(PROJECT_DIR)/Carthage/Build/iOS",
292+
);
262293
INFOPLIST_FILE = UDPClient/Info.plist;
263294
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
264295
PRODUCT_BUNDLE_IDENTIFIER = com.stansidel.UDPClient;

UDPClient.xcodeproj/xcuserdata/stan.xcuserdatad/xcschemes/UDPClient.xcscheme

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@
55
<BuildAction
66
parallelizeBuildables = "YES"
77
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "F6589E2B1C744EC600AB029C"
18+
BuildableName = "UDPClient.app"
19+
BlueprintName = "UDPClient"
20+
ReferencedContainer = "container:UDPClient.xcodeproj">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
</BuildActionEntries>
824
</BuildAction>
925
<TestAction
1026
buildConfiguration = "Debug"
@@ -13,6 +29,15 @@
1329
shouldUseLaunchSchemeArgsEnv = "YES">
1430
<Testables>
1531
</Testables>
32+
<MacroExpansion>
33+
<BuildableReference
34+
BuildableIdentifier = "primary"
35+
BlueprintIdentifier = "F6589E2B1C744EC600AB029C"
36+
BuildableName = "UDPClient.app"
37+
BlueprintName = "UDPClient"
38+
ReferencedContainer = "container:UDPClient.xcodeproj">
39+
</BuildableReference>
40+
</MacroExpansion>
1641
<AdditionalOptions>
1742
</AdditionalOptions>
1843
</TestAction>
@@ -26,6 +51,16 @@
2651
debugDocumentVersioning = "YES"
2752
debugServiceExtension = "internal"
2853
allowLocationSimulation = "YES">
54+
<BuildableProductRunnable
55+
runnableDebuggingMode = "0">
56+
<BuildableReference
57+
BuildableIdentifier = "primary"
58+
BlueprintIdentifier = "F6589E2B1C744EC600AB029C"
59+
BuildableName = "UDPClient.app"
60+
BlueprintName = "UDPClient"
61+
ReferencedContainer = "container:UDPClient.xcodeproj">
62+
</BuildableReference>
63+
</BuildableProductRunnable>
2964
<AdditionalOptions>
3065
</AdditionalOptions>
3166
</LaunchAction>
@@ -35,6 +70,16 @@
3570
savedToolIdentifier = ""
3671
useCustomWorkingDirectory = "NO"
3772
debugDocumentVersioning = "YES">
73+
<BuildableProductRunnable
74+
runnableDebuggingMode = "0">
75+
<BuildableReference
76+
BuildableIdentifier = "primary"
77+
BlueprintIdentifier = "F6589E2B1C744EC600AB029C"
78+
BuildableName = "UDPClient.app"
79+
BlueprintName = "UDPClient"
80+
ReferencedContainer = "container:UDPClient.xcodeproj">
81+
</BuildableReference>
82+
</BuildableProductRunnable>
3883
</ProfileAction>
3984
<AnalyzeAction
4085
buildConfiguration = "Debug">

UDPClient/Base.lproj/Main.storyboard

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,81 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6211" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9532" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
33
<dependencies>
4-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6204"/>
4+
<deployment identifier="iOS"/>
5+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9530"/>
6+
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
57
</dependencies>
68
<scenes>
79
<!--View Controller-->
810
<scene sceneID="tne-QT-ifu">
911
<objects>
10-
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
12+
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="UDPClient" customModuleProvider="target" sceneMemberID="viewController">
1113
<layoutGuides>
1214
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
1315
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
1416
</layoutGuides>
1517
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
1618
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
1719
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
20+
<subviews>
21+
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="9" translatesAutoresizingMaskIntoConstraints="NO" id="AHw-Sw-KAj">
22+
<rect key="frame" x="20" y="28" width="560" height="564"/>
23+
<subviews>
24+
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="localhost" borderStyle="roundedRect" placeholder="Host" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="9dO-HN-2q7">
25+
<rect key="frame" x="0.0" y="0.0" width="560" height="30"/>
26+
<fontDescription key="fontDescription" type="system" pointSize="14"/>
27+
<textInputTraits key="textInputTraits"/>
28+
</textField>
29+
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Local Port" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="e4M-GT-sfO">
30+
<rect key="frame" x="0.0" y="39" width="560" height="30"/>
31+
<fontDescription key="fontDescription" type="system" pointSize="14"/>
32+
<textInputTraits key="textInputTraits"/>
33+
</textField>
34+
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="9900" borderStyle="roundedRect" placeholder="Remote Port" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Qgi-8a-2Om">
35+
<rect key="frame" x="0.0" y="78" width="560" height="30"/>
36+
<fontDescription key="fontDescription" type="system" pointSize="14"/>
37+
<textInputTraits key="textInputTraits"/>
38+
</textField>
39+
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="Hello world!" borderStyle="roundedRect" placeholder="Message" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Jsq-7c-mRi">
40+
<rect key="frame" x="0.0" y="117" width="560" height="30"/>
41+
<fontDescription key="fontDescription" type="system" pointSize="14"/>
42+
<textInputTraits key="textInputTraits"/>
43+
</textField>
44+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kvF-NP-ujx">
45+
<rect key="frame" x="0.0" y="156" width="560" height="30"/>
46+
<state key="normal" title="Send UDP Packet"/>
47+
<connections>
48+
<action selector="sendPacket:" destination="BYZ-38-t0r" eventType="touchUpInside" id="9hs-3G-Y2g"/>
49+
</connections>
50+
</button>
51+
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4fm-G1-oag">
52+
<rect key="frame" x="0.0" y="195" width="560" height="369"/>
53+
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
54+
<fontDescription key="fontDescription" type="system" pointSize="14"/>
55+
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no"/>
56+
</textView>
57+
</subviews>
58+
</stackView>
59+
</subviews>
1860
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
61+
<constraints>
62+
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="AHw-Sw-KAj" secondAttribute="bottom" constant="8" symbolic="YES" id="3BL-3V-Ugu"/>
63+
<constraint firstItem="AHw-Sw-KAj" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="8" id="7wb-U2-HxI"/>
64+
<constraint firstItem="AHw-Sw-KAj" firstAttribute="trailing" secondItem="8bC-Xf-vdC" secondAttribute="trailingMargin" id="QTn-mi-b0O"/>
65+
<constraint firstItem="AHw-Sw-KAj" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leadingMargin" id="uIk-nM-4No"/>
66+
</constraints>
1967
</view>
68+
<connections>
69+
<outlet property="answerTextView" destination="4fm-G1-oag" id="xoT-DC-ZTP"/>
70+
<outlet property="hostTextField" destination="9dO-HN-2q7" id="k9y-jL-0xo"/>
71+
<outlet property="localPortTextField" destination="e4M-GT-sfO" id="7jn-FZ-b6X"/>
72+
<outlet property="messageTextField" destination="Jsq-7c-mRi" id="iKe-wJ-PQS"/>
73+
<outlet property="remotePortTextField" destination="Qgi-8a-2Om" id="xhx-aN-z59"/>
74+
</connections>
2075
</viewController>
2176
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
2277
</objects>
78+
<point key="canvasLocation" x="380" y="350"/>
2379
</scene>
2480
</scenes>
2581
</document>

UDPClient/ViewController.swift

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,89 @@
77
//
88

99
import UIKit
10+
import CocoaAsyncSocket
1011

11-
class ViewController: UIViewController {
12+
class ViewController: UIViewController, GCDAsyncUdpSocketDelegate {
13+
@IBOutlet weak var hostTextField: UITextField!
14+
@IBOutlet weak var localPortTextField: UITextField!
15+
@IBOutlet weak var remotePortTextField: UITextField!
16+
@IBOutlet weak var messageTextField: UITextField!
17+
@IBOutlet weak var answerTextView: UITextView!
18+
19+
var _socket: GCDAsyncUdpSocket?
20+
var socket: GCDAsyncUdpSocket? {
21+
get {
22+
if _socket == nil {
23+
guard let port = UInt16(localPortTextField.text ?? "0") where port > 0 else {
24+
log(">>> Unable to init socket: local port unspecified.")
25+
return nil
26+
}
27+
let sock = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
28+
do {
29+
try sock.bindToPort(port)
30+
try sock.beginReceiving()
31+
} catch let err as NSError {
32+
log(">>> Error while initializing socket: \(err.localizedDescription)")
33+
sock.close()
34+
return nil
35+
}
36+
_socket = sock
37+
}
38+
return _socket
39+
}
40+
set {
41+
_socket?.close()
42+
_socket = newValue
43+
}
44+
}
1245

1346
override func viewDidLoad() {
1447
super.viewDidLoad()
1548
// Do any additional setup after loading the view, typically from a nib.
49+
50+
}
51+
52+
deinit {
53+
socket = nil
1654
}
1755

1856
override func didReceiveMemoryWarning() {
1957
super.didReceiveMemoryWarning()
2058
// Dispose of any resources that can be recreated.
2159
}
60+
61+
private func log(text: String) {
62+
answerTextView.text = text + "\n" + answerTextView.text
63+
}
2264

65+
@IBAction func sendPacket(sender: AnyObject) {
66+
guard let str = messageTextField.text where !str.isEmpty else {
67+
log(">>> Cannot send packet: no data inserted")
68+
return
69+
}
70+
guard let host = hostTextField.text where !host.isEmpty else {
71+
log(">>> Cannot send packet: no host specified")
72+
return
73+
}
74+
guard let port = UInt16(remotePortTextField.text ?? "0") where port > 0 else {
75+
log(">>> Cannot send packet: no port specified")
76+
return
77+
}
78+
79+
guard socket != nil else {
80+
return
81+
}
82+
socket?.sendData(str.dataUsingEncoding(NSUTF8StringEncoding), toHost: host, port: port, withTimeout: 2, tag: 0)
83+
log("Data sent: \(str)")
84+
}
85+
86+
func udpSocket(sock: GCDAsyncUdpSocket!, didReceiveData data: NSData!, fromAddress address: NSData!, withFilterContext filterContext: AnyObject!) {
87+
guard let stringData = String(data: data, encoding: NSUTF8StringEncoding) else {
88+
log(">>> Data received, but cannot be converted to String")
89+
return
90+
}
91+
log("Data received: \(stringData)")
92+
}
2393

2494
}
2595

0 commit comments

Comments
 (0)