socket(套接字)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接,计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接,UDP连接同理。
原理图AsyncUdpSocket:
这里用到了一个三方AsyncUdpSocket,原来的下载地址不过现在不能用了,github有类似的,应该也可以直接用。这套抽奖是socket的及其简单的应用,写两套代码分别给操作端和现实端。
抽奖时用的是随机数对20取余,而最后的“现在”就是通过socket发送到现实端的。
显示端:
代码很简单,这里我就直接粘了:
#import "ViewController.h"
#import "AsyncUdpSocket.h"
#import <AVFoundation/AVFoundation.h>
#define RandomColor [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0]//随机色
#define screenWidth [UIScreen mainScreen].bounds.size.width
#define screenHeight [UIScreen mainScreen].bounds.size.height
@interface ViewController ()<AsyncUdpSocketDelegate>{
AsyncUdpSocket *_socket;
NSTimer *_timer;
NSString *_lastStr;
UIButton *startBut;
}
@property (nonatomic,strong)AVPlayer *player;
@property (nonatomic,strong)UILabel *label;
@end
@implementation ViewController
//懒加载播放器
- (AVPlayer *)player{
if (_player == nil) {
// 1.获取URL(远程/本地)
NSURL *url = [[NSBundle mainBundle] URLForResource:@"M11-01-05-57.mp3" withExtension:nil];
//NSURL *url = [NSURL URLWithString:@"http://v1.mukewang.com/a45016f4-08d6-4277-abe6-bcfd5244c201/L.mp4"];
// 2.创建AVPlayerItem
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:url];
// 3.创建AVPlayer
_player = [AVPlayer playerWithPlayerItem:item];
// 4.添加AVPlayerLayer
AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:self.player];
layer.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.width * 9 / 16);
[self.view.layer addSublayer:layer];
}
return _player;}
//搭建页面
- (void)viewDidLoad {
[super viewDidLoad];
_label = [[UILabel alloc] initWithFrame:CGRectMake(screenWidth/2-150, 100, 300, 300)];
_label.backgroundColor = [UIColor orangeColor];
_label.font = [UIFont systemFontOfSize:33.0f weight:21];
_label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:self.label];
startBut = [[UIButton alloc] initWithFrame:CGRectMake(screenWidth/2-50, screenHeight-200, 100, 50)];
[startBut setBackgroundColor:[UIColor redColor]];
[startBut setTitle:@"开始抽奖" forState:UIControlStateNormal];
[startBut addTarget:self action:@selector(LetUsBegin) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:startBut];
_socket = [[AsyncUdpSocket alloc]initIPv4];
_socket.delegate = self;
//ip 和 端口号//这个重电脑的网络看,必需要一致
[_socket bindToAddress:@"10.10.5.32" port:9444 error:nil];
//保持连接
[_socket receiveWithTimeout:-1 tag:0];
}
//点击了开始抽奖按钮
- (void)LetUsBegin{
startBut.hidden = YES;
[self.player play];
_timer = [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:@selector(ChangeLabelText) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(9* NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self stopTimer];
});
}
10秒过后停止
- (void)stopTimer{
[_timer invalidate];
_timer = nil;
if (_lastStr) {
_label.text = _lastStr;
}else{
_label.text = [NSString stringWithFormat:@"%i",arc4random()%30];
}
startBut.hidden = NO;
_label.backgroundColor = RandomColor;
_lastStr = nil;
self.player = nil;
}
定时器方法,
- (void)ChangeLabelText{
_label.text = [NSString stringWithFormat:@"%i",arc4random()%20];
_label.backgroundColor = RandomColor;
}
socket代理方法
-(BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{
_lastStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//保持连接
[_socket receiveWithTimeout:-1 tag:0];
return YES;
}
控制端:
下面放代码:
#import "ViewController.h"
#import "AsyncUdpSocket.h"
#include <ifaddrs.h>
#include <arpa/inet.h>
@interface ViewController (){
AsyncUdpSocket *_socket;
NSString *_ipAddress;
}
@property (nonatomic,strong)UITextField *tf;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//输入框
_tf = [[UITextField alloc] initWithFrame:CGRectMake(20, 100, 200, 50)];
_tf.backgroundColor = [UIColor grayColor];
[self.view addSubview:_tf];
//获取ip地址
_ipAddress = [self deviceIPAdress];
NSLog(@"%@",_ipAddress);
UIButton *but = [[UIButton alloc] initWithFrame:CGRectMake(200, 200, 80, 30)];
[but setBackgroundColor:[UIColor redColor]];
[but setTitle:@"发送" forState:UIControlStateNormal];
[but addTarget:self action:@selector(sendTheNumber) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:but];
}
//初始化socket和发送ip
- (void)sendTheNumber{
_socket = [[AsyncUdpSocket alloc]initIPv4];
_socket.delegate = self;
//ip 和 端口号
[_socket bindToAddress:_ipAddress port:9444 error:nil];
//[_socket sendData:data toAddress:@"192.168.1.160" withTimeout:-1 tag:0];
NSData* data = [_tf.text dataUsingEncoding:NSUTF8StringEncoding];
[_socket sendData:data toHost:@"10.10.5.38" port:9444 withTimeout:-1 tag:0];
_tf.text = @"";
//保持连接
[_socket receiveWithTimeout:-1 tag:0];
}
- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{
return YES;
}
//wifi下获取手机ip的方法
- (NSString *)deviceIPAdress {
NSString *address = @"an error occurred when obtaining ip address";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
success = getifaddrs(&interfaces);
if (success == 0) { // 0 表示获取成功
temp_addr = interfaces;
while (temp_addr != NULL) {
if( temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
freeifaddrs(interfaces);
NSLog(@"手机的IP是:%@", address);
return address;
}
网友评论