每次google 都是那幾篇.....而且每個都寫很不完整(很多都抄同一篇的)
搞了半天什麼CocoaAsyncSocket , GCDAsyncSocket , BSD Socket.....
沒有一篇寫比較完整,後來還好在github上有一個可以用的(不過是for Mac ,not for
iphone) 於是就仿照著寫了以後就可以用了!
--------------------------------------------------------------------------------------------------------------------------
(正文開始)
要寫socket 一定是要分兩部分 server & client , 然後在眾多的library裡面我選擇是:
AsyncUdpSocket
首先,先開一個project,然後add files to (project name)...
把AsyncUdpSocket.h / AsyncUdpSocket.m 加入(放哪邊不重要,不影響)
然後我們需要先到ViewController.h / Main.storyboard來宣告/拉一些物件
這邊(server)會需要一個輸入port 的textfield,一個按鈕 以及一個textview
別忘記要把他們兩邊做連結!
ViewControlloer.h:
//
// ViewController.h
// UdpServer
//
// Created by daniel on 2015/3/13.
// Copyright (c) 2015年 daniel. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AsyncUdpSocket.h"
@interface ViewController : UIViewController
{
AsyncUdpSocket *udpSocket;
}
@property (weak, nonatomic) IBOutlet UITextField *port;
@property (weak, nonatomic) IBOutlet UIButton *start;
@property (weak, nonatomic) IBOutlet UITextView *textview;
- (IBAction)startButton:(id)sender;
@end
ViewController.m:
//
// ViewController.m
// UdpServer
//
// Created by daniel on 2015/3/13.
// Copyright (c) 2015年 daniel. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize port;
@synthesize start;
@synthesize textview;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
udpSocket = [[AsyncUdpSocket alloc] initWithDelegate:self];//初始化
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)startButton:(id)sender {
//start udp server
NSLog(@"Socket open");
int port_int = [port.text intValue];
if(port_int < 0 || port_int > 65535)
{
port_int = 0;
}
NSError *error = nil;
if (![udpSocket bindToPort:port_int error:&error]) {
return;
}
[udpSocket receiveWithTimeout:-1 tag:0];
[port setEnabled:NO];
}
-(BOOL) onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port
{
NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if(msg)
{
//textview.text msg;
NSLog(@"message is %@",msg);
//以下這串是為了讓他能夠顯示在畫面上
NSString *temp = [NSString stringWithFormat:@"%@\n",msg];
NSMutableDictionary *attribute = [NSMutableDictionary dictionaryWithCapacity:1];
NSAttributedString *as = [[NSAttributedString alloc] initWithString:temp attributes:attribute];
//使用append的方式 ,但是他是NSAttributedString格式 所以才要先轉換,不能直接使用NSString!
[[textview textStorage] appendAttributedString:as];
}
else
{
NSLog(@"converting UTF-8 Error");
}
[udpSocket sendData:data toHost:host port:port withTimeout:-1 tag:0];
[udpSocket receiveWithTimeout:-1 tag:0];
return YES;
}
@end
在viewDidLoad這邊就是app一開始會跑的地方,當然是把socket初始化
然後在button按下去觸發的這個函式(IBAction)startButton:(id)sender )
我們需要把使用者輸入的port 放進int port_int裡面
然後如果使用者輸入數字超過0~65535這個區間 就直接給他port = 0
接著在-(BOOL) onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port
這一段,我們必須要先宣告一個NSData來接收資料(data),編碼這邊使用UTF-8
如果msg有東西則顯示在螢幕上
記得最後面要加
[udpSocket sendData:data toHost:host port:port withTimeout:-1 tag:0];
[udpSocket receiveWithTimeout:-1 tag:0];
不然只能接收一次 !
--------------------------------------------------------------------------------------------------------------------------
然後就是 Client端了
一樣是把兩邊做連結(別忘了要import "AsyncUdpSocket.h")
//
// ViewController.m
// UdpClient
//
// Created by daniel on 2015/3/13.
// Copyright (c) 2015年 daniel. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize addr;
@synthesize port;
@synthesize msg;
@synthesize sendButton;
@synthesize logView;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
udpSocket = [[AsyncUdpSocket alloc] initWithDelegate:self];
NSError *error = nil;
if(![udpSocket bindToPort:0 error:&error])
{
NSLog(@"Error binding: %@",error);
return;
}
[udpSocket receiveWithTimeout:-1 tag:0];
NSLog(@"Ready");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)send:(id)sender
{
NSString *host = [addr text];
NSLog(@"Address: %@",host);
int port_int = [[port text] integerValue];//跟原本的不太一樣
if(port_int <=0 || port > 65535)
{
NSLog(@"Valid port require");
}
NSString *message = [msg text];
if (message.length == 0) {
NSLog(@"Message require");
}
NSData *data = [message dataUsingEncoding:NSUTF8StringEncoding];
if(data != nil)
NSLog(@"data = %@",data);
[udpSocket sendData:data toHost:host port:5000 withTimeout:-1 tag:tag];
}
-(void) onUdpSocket:(AsyncUdpSocket *)sock didSendDataWithTag:(long)tag
{
//you could add checks here
}
- (void)onUdpSocket:(AsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error
{
// You could add checks here
}
-(BOOL) onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port
{
NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if(msg)
{
NSLog(@"Receive: %@",msg);
}
else
{
NSLog(@"Receive Unknown message from %@:%hu",host,port);
}
[udpSocket receiveWithTimeout:-1 tag:0];
return YES;
}
@end
在viewDidLoad這邊一樣要先初始化udpSocket,然後在sendbutton觸發這個action的
event這邊:
-(IBAction)send:(id)sender
{
NSString *host = [addr text];
把使用者輸入的ip放入host變數
NSLog(@"Address: %@",host);
int port_int = [port text];
把使用者輸入的port放進去port_int變數
if(port_int <=0 || port > 65535)
{
NSLog(@"Valid port require");
}
NSString *message = [msg text];
把使用者輸入的message放進去message變數
if (message.length == 0) {
NSLog(@"Message require");
}
NSData *data = [message dataUsingEncoding:NSUTF8StringEncoding];
把要傳出去的message轉換為NSData型態,編碼使用utf-8
if(data != nil)
NSLog(@"data = %@",data);
[udpSocket sendData:data toHost:host port:5000 withTimeout:-1 tag:tag];
這邊為了測試方便直接把port 寫死5000,其實應該要寫port:port_int才對
}
好了!
這樣server / client 都有了 就可以開始通訊拉!
client + server(更新連結@2015.11.17)
https://mega.nz/#!HI0h0ahR! iNpaCRvpT-rwTkJrW-oowWNnUf_ GsbD-OxQKmFmNRQg
https://mega.nz/#!yNF2CS6a! QjfL6gMO7qdFJugvKaaVDoUSGgtfU8 m_d_XtRM_TVfk
https://mega.nz/#!HI0h0ahR!
https://mega.nz/#!yNF2CS6a!
附上程式碼!
https://www.youtube.com/watch?v=wNX29RxA2K8&feature=youtu.be
https://www.youtube.com/watch?v=mDJv2UHnyZg&feature=youtu.be
附上實測證明可以用