网络

利用Socket模拟10086服务器读写数据

2016-03-09  本文已影响172人  Alexander

前言

步骤 :

#import <Foundation/Foundation.h>

@interface WGServicerListener : NSObject

/** 定义一个对象方法,用于开启10086服务器 */
- (void)start;

@end

#import <Foundation/Foundation.h>
#import "WGServicerListener.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        // 创建监听100086服务器的对象,只要连接到IP地址,就开启10086服务器
        WGServicerListener *listener = [[WGServicerListener alloc] init];

        // 开启服务器
        [listener start];

        // 保证开启服务器以后,一直处于开启状态
        [[NSRunLoop mainRunLoop] run];

        // 小常识 : 服务器是不会停的(所以, 需要手动开启一个主运行循环)
    }
    return 0;
}


#import "WGServicerListener.h"
#import "GCDAsyncSocket.h"

@interface WGServicerListener ()<GCDAsyncSocketDelegate>

// 服务器Soket
@property(nonatomic, strong) GCDAsyncSocket *serverSocket;

// 保存客户端所有的Socket对象
@property(nonatomic, strong) NSMutableArray *clientSockets;

@end

@implementation WGServicerListener

#pragma mark -  懒加载
- (NSMutableArray *)clientSockets
{
    if (_clientSockets == nil) {

        _clientSockets = [NSMutableArray array];
    }
    return _clientSockets;
}

- (void)start {

    // 1, 创建服务器的socket对象,serverSocket只会监听有没有客户端请求连接
    GCDAsyncSocket *serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];

    // 2, 绑定和监听客户端的连接
    NSError *error = nil;
    [serverSocket acceptOnPort:1688 error:&error];

    // 判断error是否有值,如果有值表示开启失败
    if (!error) {

        // 开启成功
        NSLog(@"10086服务器已开启");
    } else
    {
    // 开启失败
        NSLog(@"10086服务器开启失败 : %@",error);
    }

    // 保存服务器的Socket对象
    self.serverSocket = serverSocket;
}
// 需要监听服务器是否有连接到新的客户端,所以, 监听方法是属于协议中的方法,要遵守协议

/**
 * 只要有新的端口和服务器连接就会调用该方法.
 * 前面个sock是服务器的端口, 后面个newSocket是客户端的端口,可以自定义参数名
 */
- (void)socket:(GCDAsyncSocket *)serverSocket didAcceptNewSocket:(GCDAsyncSocket *)clientSocket
{

    // 将连接进来的客户端的Socket对象保存到数组中
    [self.clientSockets addObject:clientSocket];

    // 只要开启服务就提示用户有什么类型的服务
    NSMutableString *promptStr = [NSMutableString string];
    [promptStr appendString:@"欢迎来到10086在线服务,请输入下面的数字选择服务\n"];
    [promptStr appendString:@"[0]在线充值\n"];
    [promptStr appendString:@"[1]在线投诉\n"];
    [promptStr appendString:@"[2]优惠信息\n"];
    [promptStr appendString:@"[3]special services\n"];
    [promptStr appendString:@"[4]退出\n"];

    // 客户端写入数据
    [clientSocket writeData:[promptStr dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];

    // 监听客户端有没有上传数据
    [clientSocket readDataWithTimeout:-1 tag:0];
}
/**
 * 监听客户端有没有输入数据,只要客户端上传了数据,那么就一定会调用下面这个方法
 *
 */
- (void)socket:(GCDAsyncSocket *)clientSocket didReadData:(NSData *)data withTag:(long)tag
{

    NSLog(@"客户端输入数据了");  // 测试用

    // 此时,服务器接收到的是一个NSData,我们需要将NSData转为一个字符串
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    // 将字符串转为数字,使用switch输出对应的字符串
    NSInteger number = [str integerValue];
    NSString *responseStr = nil;
    switch (number) {
        case 0:
            responseStr = @"充值服务进行中...\n";
            break;
        case 1:
            responseStr = @"10086的投诉服务几乎零处理...\n";
            break;
        case 2:
            responseStr = @"几乎所有优惠信息都是骗人的...\n";
            break;
        case 3:
            responseStr = @"特殊服务倒是做的勤快...\n";
            break;
        case 4:
            responseStr = @"您已经退出了,并且扣了50块钱\n";
            break;
        default:

            break;
    }

    // 服务器读取客户端上传的数据
    [clientSocket writeData:[responseStr dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];

    // 当number = 4 说明用户需要退出,但是我们需要将客户端和服务器之间的连接断开
    if (number == 4) {

        // 将数组中的客户端全部移除掉
        [self.clientSockets removeObject: clientSocket];
    }

    // 只要客户端上传1次数据,服务器都需要监听它
    [clientSocket readDataWithTimeout:-1 tag:0];
}
上一篇下一篇

猜你喜欢

热点阅读