我是靠谱客的博主 顺利冰棍,最近开发中收集的这篇文章主要介绍iOS中基于Socket 的的网络通信,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

     ViewController.h

#import <UIKit/UIKit.h>

#import <CoreFoundation/CoreFoundation.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 8734	   //将端口设置为8734,可以根据具体情况改变

@interface ViewController : UIViewController<NSStreamDelegate>
{
	int flag ; //操作标志 0为发送 1为接收
}

@property (nonatomic, retain) NSInputStream *inputStream;
@property (nonatomic, retain) NSOutputStream *outputStream;

@property (weak, nonatomic) IBOutlet UILabel *message;	//在客户端显示来自服务端的消息

- (IBAction)sendData:(id)sender;	  //发送客户端的消息
- (IBAction)receiveData:(id)sender;   //接收来自服务端的消息

@end
ViewController.m
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
	[super viewDidLoad];
	
}

- (void)didReceiveMemoryWarning
{
	[super didReceiveMemoryWarning];
}

//初始化客户端网络连接
- (void)initNetworkCommunication
{
	
	CFReadStreamRef readStream;
	CFWriteStreamRef writeStream;
	//这里需要填写 IP 地址,根据自己路由可以用的 IP来定,这里是192.168.1.103,如果不知道可以下载 IP 扫描器
	CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.1.103", PORT, &readStream, &writeStream);
	
	self.inputStream = (__bridge_transfer NSInputStream *)readStream;  //将CFStream对象转化为NSStream对象
	self.outputStream = (__bridge_transfer NSOutputStream
					 *)writeStream;			  //将CFStream对象转化为NSStream对象
	[self.inputStream setDelegate:self];
	[self.outputStream setDelegate:self];
	[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
							forMode:NSDefaultRunLoopMode];	//NSStream 方法 scheduleInRunLoop: 设置 Run Loop
	[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
							 forMode:NSDefaultRunLoopMode];
	[self.inputStream open];   //NSStream 的 open 方法来打开数据流对象
	[self.outputStream open];
	
}

//关闭数据流操作
-(void)close
{
	[self.outputStream close];
	[self.outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
	[self.outputStream setDelegate:nil];
	[self.inputStream close];
	[self.inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
	[self.inputStream setDelegate:nil];
}

//从客户端发送数据事件方法
- (IBAction)sendData:(id)sender {
	flag = 0;   //表示发送
	[self initNetworkCommunication];
	
}

//从服务端接收数据事件方法
- (IBAction)receiveData:(id)sender {
	flag = 1;   //表示接收
	[self initNetworkCommunication];
	
}

-(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
	NSString *event;
	switch (streamEvent) {
		case NSStreamEventNone:  //没有事件发生
			event = @"NSStreamEventNone";
			break;
		case NSStreamEventOpenCompleted:  //成功打开流
			event = @"NSStreamEventOpenCompleted";
			break;
		case NSStreamEventHasBytesAvailable:   //这个流有数据可以读,在读取数据时使用
			event = @"NSStreamEventHasBytesAvailable";
			if (flag ==1 && theStream == _inputStream) {
				NSMutableData *input = [[NSMutableData alloc] init];
				uint8_t buffer[2048]; //读取数据准备缓冲区,本例中设置的是2048字节,这个大小会对流的读取有很大影响   
				int len;
				while([self.inputStream hasBytesAvailable])
				{
					len = [self.inputStream read:buffer maxLength:sizeof(buffer)];  //读取数据到缓冲区
					if (len > 0)
					{
						[input appendBytes:buffer length:len];
					}
				}
				NSString *resultstring = [[NSString alloc] initWithData:input encoding:NSUTF8StringEncoding];
				NSLog(@"接收:%@",resultstring);
				self.message.text = resultstring;
			}
			break;
		case NSStreamEventHasSpaceAvailable:   //这个流可以接收数据的写入,在写数据时使用
			 event = @"NSStreamEventHasSpaceAvailable";
            if (data && data.length != 0) {
                if (theStream == _outputStream) {
                    //输出
                    NSString * snStr = [NSString stringWithFormat:@"%@",[_dic objectForKey:@"sn"]];
                    NSString * comStr = [NSString stringWithFormat:@"%@",data ];
                    const char * comChar = [comStr UTF8String];
                    char * comUnit = [[comStr dataUsingEncoding:NSUTF8StringEncoding]bytes];
                    strcpy(comUnit, comChar);
                    if ([comStr intValue] == 0) {
                        comUnit[0] = 00;
                    }else if ([comStr intValue] == 1){
                        comUnit[0] = 01;
                        
                    }else if ([comStr intValue] == 2){
                        comUnit[0] = 02;
                        
                    }
                    //                memcpy(comUnit,[comStr UTF8String], [comStr length]+1);
                    const char * snChar = [snStr UTF8String];
                    char * bufChar = [[snStr dataUsingEncoding:NSUTF8StringEncoding]bytes];
                    strcpy(bufChar, snChar);
                    
                    UInt8 i=0;
                    unsigned char tcpcmd[44]={(char)0x00,(char)0x2C,(char)0xAA,(char)0x55,(char)0x0,(char)0x0,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x31,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x39,(char)0x31,(char)0x04 };
                    while(strlen(bufChar)!=0)
                    {
                        tcpcmd[31+i]=*bufChar++;
                        i++;
                    }
                    


                    tcpcmd[43]=*comUnit;
                    NSData *senddata = [NSData dataWithBytes: tcpcmd  length:44];
                    NSLog(@"tcpcmd-%d",strlen((const char*)tcpcmd)+1);
                    [_outputStream write:[senddata bytes] maxLength: 44];
                    //必须关闭输出流否则,服务器端一直读取不会停止,
                    [_outputStream close];
                }
                data = @"";
//                [self alter:@"操作成功"];
                [self performSelector:@selector(getState) withObject:nil afterDelay:2.0f];

            }


			break;
		case NSStreamEventErrorOccurred:	  //数据流发生错误
			event = @"NSStreamEventErrorOccurred";
			[self close];
			break;
		case NSStreamEventEndEncountered:	 //数据流结束
			event = @"NSStreamEventEndEncountered";
			NSLog(@"Error:%d:%@",[[theStream streamError] code], [[theStream streamError] localizedDescription]);
			break;
		default:
			[self close];
			event = @"Unknown";
			break;
	}

}

@end

//---------------------------------------------------------------------------------------------------------------------

在iOS开发中使用socket,一般都是用第三方库AsyncSocket,不得不承认这个库确实很强大。下载地址CocoaAsyncSocket   


导入

AsyncSocket.h


#import <Foundation/Foundation.h>

#import "AsyncSocket.h"

enum{

    SocketOfflineByServer,// 服务器掉线,默认为0

    SocketOfflineByUser,  // 用户主动cut

    SocketOfflineByWifiCut,

};

@interface LGSocketServe : NSObject<AsyncSocketDelegate>

@property (nonatomic, strong) AsyncSocket         *socket;       // socket

 @property (nonatomic, retain) NSTimer             *heartTimer;   // 心跳计时器

//  socket连接

- (void)startConnectSocket;

+ (LGSocketServe *)sharedSocketServe;

 -(void)cutOffSocket;

// 发送消息

- (void)sendMessage:(id)message;

@end

---------------------------------------------------------------------------------------

#import "LGSocketServe.h"

//自己设定

#define HOST @"192.168.1.218"

#define PORT 9091

#define TIME_OUT 20

#define MAX_BUFFER 1024

#define READ_TIME_OUT -1

#define WRITE_TIME_OUT -1


@implementation LGSocketServe



static LGSocketServe *socketServe = nil;


#pragma mark public static methods



+ (LGSocketServe *)sharedSocketServe {

    @synchronized(self) {

        if(socketServe == nil) {

            socketServe = [[[self class] alloc] init];

        }

    }

    return socketServe;

}



+(id)allocWithZone:(NSZone *)zone

{

    @synchronized(self)

    {

        if (socketServe == nil)

        {

            socketServe = [super allocWithZone:zone];

            return socketServe;

        }

    }

    return nil;

}


- (void)startConnectSocket

{

    self.socket = [[AsyncSocket alloc] initWithDelegate:self];

    [self.socket setRunLoopModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];

    if ( ![self SocketOpen:HOST port:PORT] )

    {

        

    }

    

}

-(void)cutOffSocket

{

    self.socket.userData = SocketOfflineByUser;

    [self.socket disconnect];

}

- (NSInteger)SocketOpen:(NSString*)addr port:(NSInteger)port

{

    

    if (![self.socket isConnected])

    {

        NSError *error = nil;

        [self.socket connectToHost:addr onPort:port withTimeout:TIME_OUT error:&error];

    }

    

    return 0;

}


- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port

{

    //这是异步返回的连接成功,

    NSLog(@"didConnectToHost");

    

    //通过定时器不断发送消息,来检测长连接

    self.heartTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(checkLongConnectByServe) userInfo:nil repeats:YES];

    [self.heartTimer fire];

}


// 心跳连接

-(void)checkLongConnectByServe{

    

    // 向服务器发送固定可是的消息,来检测长连接

    NSString *longConnect = @"connect is here";

    NSData   *data  = [longConnect dataUsingEncoding:NSUTF8StringEncoding];

    [self.socket writeData:data withTimeout:1 tag:1];

}


- (void)onSocketDidDisconnect:(AsyncSocket *)sock

{

    

    NSLog(@"7878 sorry the connect is failure %ld",sock.userData);

    

    if (sock.userData == SocketOfflineByServer) {

        // 服务器掉线,重连

        [self startConnectSocket];

    }

    else if (sock.userData == SocketOfflineByUser) {

        

        // 如果由用户断开,不进行重连

        return;

    }else if (sock.userData == SocketOfflineByWifiCut) {

        

        // wifi断开,不进行重连

        return;

    }

    

}

- (void)sendMessage:(id)message

{

    //像服务器发送数据

//    NSData *cmdData = [message dataUsingEncoding:NSUTF8StringEncoding];

    [self.socket writeData:message withTimeout:WRITE_TIME_OUT tag:1];

}


//发送消息成功之后回调

- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag

{

    //读取消息

    [self.socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];

}


//接受消息成功之后回调

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag

{

    //服务端返回消息数据量比较大时,可能分多次返回。所以在读取消息的时候,设置MAX_BUFFER表示每次最多读取多少,当data.length < MAX_BUFFER我们认为有可能是接受完一个完整的消息,然后才解析

    if( data.length < MAX_BUFFER )

    {

        //收到结果解析...

        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];

        NSLog(@"%@",dic);

        //解析出来的消息,可以通过通知、代理、block等传出去

        

    }

    

    

    [self.socket readDataWithTimeout:READ_TIME_OUT buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];

}


- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err

{

    NSData * unreadData = [sock unreadData]; // ** This gets the current buffer

    if(unreadData.length > 0) {

        [self onSocket:sock didReadData:unreadData withTag:0]; // ** Return as much data that could be collected

    } else {

        

        NSLog(@" willDisconnectWithError %ld   err = %@",sock.userData,[err description]);

        if (err.code == 57) {

            self.socket.userData = SocketOfflineByWifiCut;

        }

    }

    

}

@end



最后

以上就是顺利冰棍为你收集整理的iOS中基于Socket 的的网络通信的全部内容,希望文章能够帮你解决iOS中基于Socket 的的网络通信所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(40)

评论列表共有 0 条评论

立即
投稿
返回
顶部