采用异步socket实现客户端和服务端的通信

简介: 采用异步socket实现客户端和服务端的通信

MAC系统基于UNIX的核心系统增强了系统的稳定性、性能以及响应能力。由于unix需要付费,以及版本基本上不更新,很多采用unix系统的电脑转用linux,unix处于停滞不前状态,而linux由于是开源的,免费的,所以全球很多技术大牛在不断改进它,给它增加新技术,增加新理念,使它日新月异的发展。所以mac os后期主要借鉴linux的新技术,所以现在的mac os越来越像linux,linux也是来源于unix,他们师兄弟两个青出于蓝而胜于蓝。因此linux的socket的编程对苹果系统仍然有效。可以通过socket直接发送数据请求,可以通过fd创建多个连接,通过select对各个fd进行监控。要注意黏包的问题,可能网络不好或一段高频率的写数据不同的消息格式数据,开始可能没有立刻收到响应消息,有可能突然收到多个消息拼接在一起的字符串。有一种通而不达的情况,可能刚创建select后用select监听,服务器返回准备中,但是直到3.5分钟才能返回失败。

这个是我当时研究socket长连接的例子,由于非完整项目,没有解决粘包问题,由于只实现了部分功能,没有对消息格式进行严格定义和解析。只是实现了异步socket通信(收发消息)部分。不过我做的新项目这类的项目已经完美解决,由于公司信息案安全原因,不能泄露具体项目内容,但是它的原理是一样的,而且篇文章基本上没有加业务逻辑,所以更简单更容易看懂。

运行在mac的socket服务器demo下载地址:

http://download.csdn.net/download/jia12216/8929167

socket客户端app下载地址:http://download.csdn.net/download/jia12216/8929153

用java写的socket服务器测试桩下载地址:http://download.csdn.net/download/jia12216/8929101

运行在window电脑上socket服务器demo下载地址:http://download.csdn.net/download/jia12216/8929085

第三方库socket异步通信(robbiehanson/CocoaAsyncSocket)下载地址:https://github.com/robbiehanson/CocoaAsyncSocket/

注意:

inet_addr(“172.16.28.153”);这个要填你服务运行的电脑的ip,若有域名最好填域名(如:www.baidu.com).

.sin_port = htons(9123);这个你要连接的端口号,服务器和客户端的域名和端口好要一致。

客户端代码:

-(void)creatPushConnection
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        unsigned char recv_msg[BUFFER_SIZE+3];
        NSString *dec = nil;
        NSInteger iStart = 0;
        unsigned char input_msg[4096];
        int server_sock_fd;
        int sd;
        BOOL handleFlag = NO;
        NSDate *curDate =  nil;
        unsigned char msg[4096+1];
        NSUInteger len = 0;
        //unsigned int m = 0;
        long n = 0;
        unsigned char c;


        long byte_num = 0;
        unsigned char *p = recv_msg;
        char arr[BUFFER_SIZE+1];
        long m = 0, m1 = 0;
        NSString *message = nil;
        NSString *str1=nil;
        NSString *str2=nil;
        unsigned int k = 0;
        NSError *error = nil;
        Boolean bFlag = YES;
        Boolean bstrEndFlag = NO;
        NSData *da = nil;
        g_LoginShiftState = SHIFT_STATE_INIT;

        g_fd = -1;
        server_sock_fd = -1;
    SKIP:
        //注意这段绑定ip和端口号的代码要放在这里防止出现网络类型变更,如:从wifi切换到4G,或4G切换到3G
        struct sockaddr_in server_addr;
        server_addr.sin_len = sizeof(struct sockaddr_in);
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(9123);
        //server_addr.sin_addr.s_addr = inet_addr("172.16.28.106");
        //server_addr.sin_addr.s_addr = inet_addr("172.16.28.25");
        //server_addr.sin_addr.s_addr = inet_addr("172.16.28.157");
        //server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
        server_addr.sin_addr.s_addr = inet_addr("172.16.28.153");
        bzero(&(server_addr.sin_zero),8);

        if(g_fd != -1)
        {
            close(g_fd);

        }
        g_pushTime = 0;
        g_LoginShiftState = SHIFT_STATE_INIT;
        g_fd = -1;
        server_sock_fd = -1;

        server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
        sd = server_sock_fd;
        if (server_sock_fd == -1) {
            NSLog(@"socket error");
            return;
        }

        while(1)
        {
            g_fdWriteFlag = YES;
            //将打开的socket设为非阻塞的,可以用fcntl(socket, F_SETFL, O_NDELAY)完成,网络不通75秒才返回结果
            fcntl(socket, F_SETFL, O_NDELAY);
            int i = connect(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in));
            NSLog(@"i= %d\n", i);
            //发connect调用,这时返回-1,但是errno被设为EINPROGRESS,意即connect仍旧在进行还没有完成. 
            //getsockopt(socket, SOL_SOCKET, SO_ERROR, &error, sizeof(int)); 
来得到error的值,如果为零,则connect成功. 
            if ( i ==0) {
                g_fd = server_sock_fd;;
                fd_set client_fd_set;
                fd_set read_fd_set;
                struct timeval tv;
                tv.tv_sec = 10;
                tv.tv_usec = 0;
                //int max_fd = pipeFd;
                int max_fd = server_sock_fd;
                i = 0;

                while (1) {
                    g_fdWriteFlag = YES;
                    bzero(input_msg, 1024);
                    FD_ZERO(&read_fd_set);
                    FD_SET(server_sock_fd, &read_fd_set);
                    struct timeval tv;
                    tv.tv_sec = 1;
                    tv.tv_usec = 0;
                    i = 0;
                    if(max_fd < server_sock_fd)
                    {
                        max_fd = server_sock_fd;

                    }
                    int ret = select(max_fd + 1, &read_fd_set, NULL, NULL, &tv);
                    if (ret < 0 ) {
                        NSLog(@"select 出错!\n");
                        goto SKIP;
                    }
                    else if(ret ==0){
                        NSLog(@"select 超时!\n");

                        FD_ZERO(&client_fd_set);
                        FD_ZERO(&read_fd_set);
                        FD_SET(server_sock_fd, &client_fd_set);
                        FD_SET(server_sock_fd, &read_fd_set);

                        tv.tv_sec = 1;
                        tv.tv_usec = 0;
                        //socket一般都处于可写状态,除了网卡满了写不进去的罕见情况,所以该处侦听一般都是立刻响应
                        ret = select(max_fd + 1, &read_fd_set, &client_fd_set, NULL, &tv);
                        //[g_puTc lock];
                        if (ret < 0 ) {
                            NSLog(@"select 出错!\n");
                            //[g_puTc unlock];
                            goto SKIP;
                        }
                        else if(ret ==0){
                            NSLog(@"select 超时!\n");
                            //[g_puTc unlock];
                            continue;
                        }
                        else
                        {
                            //先把消息接收过来,后面再处理,防止再处理消息时,连接异常。
                            if (FD_ISSET(server_sock_fd, &read_fd_set))
                            {
                                NSLog(@"ret2= %d\n", ret);
                                bzero(recv_msg, BUFFER_SIZE);
                                long byte_num = recv(server_sock_fd,recv_msg,BUFFER_SIZE,0);
                                if (byte_num > 0) {
                                    if (byte_num > BUFFER_SIZE) {
                                        byte_num = BUFFER_SIZE;
                                    }
                                    recv_msg[byte_num] = '\0';
                                    NSLog(@"服务器:%s\n",recv_msg);
                                    handleFlag = YES;
                                }else if(byte_num < 0){
                                    NSLog(@"接收消息出错!\n");
                                    //从实际运行上发现,若出现接收消息错误,后面无论如何接收消息都报同样的错误,所以还是关闭SOCKET,重新建立连接吧!
                                    close(server_sock_fd);
                                    goto SKIP;
                                }else{
                                    //当socket可读,但是读到的字节数为0,说明是服务端退出
                                    close(server_sock_fd);
                                    NSLog(@"服务器端退出!\n");
                                    goto SKIP;
                                }

                            }

                            //判断是否可写,若可写,并且有消息可以发送就像服务器推送消息。
                            if (FD_ISSET(server_sock_fd, &client_fd_set)) {
                                bzero(input_msg, BUFFER_SIZE);
                                if((g_LoginShiftState == SHIFT_STATE_INIT) || (g_LoginShiftState == SHIFT_STATE_UNLOGIN))
                                {
                                    bzero(msg, 4096);
                                    snprintf(msg, sizeof(msg), "#################################################################POSITON latitude = %f, longitude = %f", g_latitude, g_longitude);
                                    bzero(input_msg, 4096);

                                    snprintf(msg, sizeof(msg), "{\"head\":{\"token\":\"%s\",\"cmd\":\"0002\",\"result\":\"0\",\"ecode\":\"\",\"msg\":\"中国01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789e\"},\"body\":{}}", [g_token UTF8String]);

                                    NSLog(@"msg= %s\n", msg);
                                    len = strlen(msg);
                                    snprintf(input_msg+2, len+1, "%s", msg);
                                    NSUInteger m = 0;
                                    NSUInteger j = 1;
                                    m  = len;
                                    if(m/256 == 0)
                                    {
                                        input_msg[j--] = m % 256;
                                        input_msg[j] = 0;
                                    }
                                    else if(m/65536 == 0)
                                    {
                                        input_msg[j--] = m % 256;
                                        input_msg[j] = m/256;
                                    }
                                    NSLog(@"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@input_msg1=%s\n", input_msg+2);

                                    ret = send(server_sock_fd, input_msg, len  + 2, 0);
                                    if (ret == -1) {
                                        NSLog(@"发送消息出错!\n");
                                        NSLog(@"ret7= %d\n", ret);
                                    }
                                    else
                                    {
                                        if((g_LoginShiftState == SHIFT_STATE_INIT) || (g_LoginShiftState == SHIFT_STATE_UNLOGIN))
                                        {
                                            g_LoginShiftState = SHIFT_STATE_LOGINING;
                                        }
                                        NSLog(@"ret8= %d\n", ret);

                                    }
                                }
                                else if(g_LoginShiftState == SHIFT_STATE_LOGINING)
                                {
                                    curDate = [NSDate date];

                                    NSTimeInterval nowTime = [curDate timeIntervalSince1970]*1;

                                    if(nowTime - g_pushTime >= 15*2)
                                    {
                                        bzero(msg, 300);
                                        snprintf(msg, sizeof(msg), "#################################################################POSITON latitude = %f, longitude = %f", g_latitude, g_longitude);
                                        bzero(input_msg, BUFFER_SIZE);

                                        snprintf(msg, sizeof(msg), "[{\"head\":{\"token\":\"%s\",\"cmd\":\"0001\",\"result\":\"0\",\"ecode\":\"\",\"msg\":\"中国\"},\"body\":{\"latitude\":%f,\"longitude\":%f}}]", [g_token UTF8String], g_latitude, g_longitude);

                                        NSLog(@"msg= %s\n", msg);
                                        len = strlen(msg);
                                        snprintf(input_msg+2, len+1, "%s", msg);
                                        NSUInteger m = 0;
                                        NSUInteger j = 1;
                                        m  = len;
                                        if(m/256 == 0)
                                        {
                                            input_msg[j--] = m % 256;
                                            input_msg[j] = 0;
                                        }
                                        else if(m/65536 == 0)
                                        {
                                            input_msg[j--] = m % 256;
                                            input_msg[j] = m/256;
                                        }
                                        NSLog(@"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@input_msg2=%s\n", input_msg+2);
                                        while (!g_fdWriteFlag)
                                        {
                                            sleep(3);
                                        }
                                        g_fdWriteFlag = NO;
                                        ret = send(server_sock_fd, input_msg, len + 2, 0);
                                        if (ret == -1) {
                                            NSLog(@"发送消息出错!\n");
                                            NSLog(@"ret7= %d\n", ret);
                                            g_fdWriteFlag = YES;
                                            //[g_puTc unlock];
                                            goto SKIP;
                                        }
                                        else
                                        {
                                            NSLog(@"ret8= %d\n", ret);
                                            g_pushTime = nowTime;
                                        }
                                        ret = send(server_sock_fd, input_msg, len + 2, 0);
                                        if (ret == -1) {
                                            NSLog(@"发送消息出错!\n");
                                            NSLog(@"ret7= %d\n", ret);
                                            g_fdWriteFlag = YES;
                                            //[g_puTc unlock];
                                            goto SKIP;
                                        }
                                        else
                                        {
                                            NSLog(@"ret8= %d\n", ret);
                                            g_pushTime = nowTime;
                                        }
                                        ret = send(server_sock_fd, input_msg, len + 2, 0);
                                        if (ret == -1) {
                                            NSLog(@"发送消息出错!\n");
                                            NSLog(@"ret7= %d\n", ret);
                                            g_fdWriteFlag = YES;
                                            //[g_puTc unlock];
                                            goto SKIP;
                                        }
                                        else
                                        {
                                            NSLog(@"ret8= %d\n", ret);
                                            g_pushTime = nowTime;
                                        }

                                        g_fdWriteFlag = YES;
                                    }

                                }
                            }
                            //在此处处理服务器发过来的消息
                            //handleMessage

                        }
                        //[g_puTc unlock];
                        continue;
                    }
                    else
                    {
                        i = 10 - tv.tv_sec;
                        NSLog(@"i= %d\n", i);
                        NSLog(@"&client_fd_set= %d\n", &client_fd_set);


                        if (FD_ISSET(server_sock_fd, &read_fd_set))
                        {
                            NSLog(@"ret2= %d\n", ret);
                            str1 = nil;
                            str2 = nil;
                            bFlag = YES;

                            bzero(recv_msg, BUFFER_SIZE+3);
                            byte_num = recv(server_sock_fd,recv_msg,MESSAGE_HEADER_SIZE,0);
                            if (byte_num == 2)
                            {
                                //                            if (byte_num > BUFFER_SIZE) {
                                //                                byte_num = BUFFER_SIZE;
                                //                            }
                                //recv_msg[byte_num] = '\0';
                                //NSLog(@"服务器:%s\n",recv_msg+2);
                                //dec = nil;
                                //iStart =h 0;
                                //bzero(arr, BUFFER_SIZE+1);
                                //memcpy(arr, recv_msg, BUFFER_SIZE);


                                c = recv_msg[0];
                                //NSLog(@"服务器:%d\n",c);
                                n = c*256;
                                //NSLog(@"服务器:%d\n",n);
                                c = recv_msg[1];
                                //NSLog(@"服务器:%d\n",c);
                                n = n + c;
                                while (1)
                                {
                                    NSLog(@"服务器:消息队列解析。\n");
                                    NSLog(@"服务器:%ld\n",n);
                                    m1 = BUFFER_SIZE;
                                    bstrEndFlag = NO;
                                    if(n == 0)
                                    {
                                        NSLog(@"服务器:消息错误\n");
                                        break;
                                    }
                                    else
                                    {
                                        bzero(recv_msg, BUFFER_SIZE+3);
                                        if(n <= BUFFER_SIZE)
                                        {
                                            //n = n;
                                            byte_num = recv(server_sock_fd,recv_msg,n + 2,0);
                                            NSLog(@"服务器:n = %d, byte_num = %d\n",n, byte_num);
                                            if(byte_num == n)
                                            {
                                                str1 = [NSString stringWithCString:recv_msg encoding:NSUTF8StringEncoding];
                                                NSLog(@"服务器:%@\n",str1);
                                                break;
                                            }
                                            else if(byte_num == n + 2)
                                            {
                                                str1 = [NSString stringWithCString:recv_msg encoding:NSUTF8StringEncoding];
                                                NSLog(@"服务器:%@\n",str1);
                                                c = recv_msg[byte_num-2];
                                                //NSLog(@"服务器:%d\n",c);
                                                n = c*256;
                                                //NSLog(@"服务器:%d\n",n);
                                                c = recv_msg[byte_num-1];
                                                //NSLog(@"服务器:%d\n",c);
                                                n = n + c;
                                                break;
                                            }
                                            else
                                            {
                                                NSLog(@"服务器:消息格式错误\n");
                                                break;

                                            }

                                            //                                    str1 = nil;
                                            //                                    str2 = nil;
                                            //
                                            //                                    bzero(recv_msg, BUFFER_SIZE+1);
                                            //                                    byte_num = recv(server_sock_fd,recv_msg,MESSAGE_HEADER_SIZE,0);
                                            //                                    if (byte_num != 2)
                                            //                                    {
                                            //                                        break;
                                            //                                    }
                                        }
                                        else
                                        {
                                            while (m1 > 0)
                                            {
                                                NSLog(@"服务器:消息字符串解析。\n");
                                                bzero(recv_msg, BUFFER_SIZE+3);
                                                byte_num = recv(server_sock_fd,recv_msg,m1,0);
                                                if((byte_num != BUFFER_SIZE) && (!bstrEndFlag))
                                                {
                                                    NSLog(@"服务器:消息格式错误\n");
                                                    bFlag = NO;
                                                    break;
                                                }
                                                else if((byte_num == m1) && (m1 == n + 2) && (bstrEndFlag))
                                                {
                                                    bFlag = YES;
                                                    c = recv_msg[m1-2];
                                                    NSLog(@"服务器:c = %d\n",c);
                                                    n = c*256;
                                                    c = recv_msg[m1-1];
                                                    NSLog(@"服务器:c = %d\n",c);
                                                    n = n + c;
                                                    NSLog(@"服务器:n = %d\n",n);
                                                    recv_msg[m1-2] ='\0';
                                                    recv_msg[m1-1] = '\0';
                                                }
                                                else if((byte_num < n) && (bstrEndFlag))
                                                {
                                                    NSLog(@"服务器:消息格式错误\n");
                                                    bFlag = NO;
                                                    break;

                                                }
                                                else if((byte_num == n) && (m1 == n + 2) && (bstrEndFlag))
                                                {
                                                    bFlag = NO;
                                                }
                                                NSLog(@"服务器:((byte_num == n) && (m1 == n + 2) && (bstrEndFlag)) = %d\n",((byte_num == n) && (m1 == n + 2) && (bstrEndFlag)));
                                                NSLog(@"服务器:byte_num = %d, n = %d, bFlag = %d, m1 = %d\n",byte_num, n, bFlag, m1);
                                                if(str1 == nil)
                                                {
                                                    str1 = [NSString stringWithCString:recv_msg encoding:NSUTF8StringEncoding];
                                                }
                                                else
                                                {
                                                    str2 = [NSString stringWithCString:recv_msg encoding:NSUTF8StringEncoding];
                                                    str1 = [str1 stringByAppendingString:str2];
                                                }
                                                if(bstrEndFlag)
                                                {
                                                    NSLog(@"服务器:%@\n",str1);
                                                    break;
                                                }

                                                //NSLog(@"服务器:m1 == BUFFER_SIZE = %d\n",m1 == BUFFER_SIZE);
                                                n = n - BUFFER_SIZE;
                                                if(n > BUFFER_SIZE)
                                                {
                                                    m1 = BUFFER_SIZE;
                                                }
                                                else if((m1 == BUFFER_SIZE) && (n > 0))
                                                {
                                                    m1 = n + 2;
                                                    bstrEndFlag = YES;
                                                    NSLog(@"服务器:m1 = %ld\n",m1);
                                                }
                                                else
                                                {
                                                    break;
                                                }
                                            }
                                            if(bFlag)
                                            {
                                                NSLog(@"服务器:%@\n",str1);
                                                //在此处处理服务器发过来的消息
                                                //handleMessage
                                                str1 = nil;
                                                str2 = nil;
                                            }
                                            else
                                            {
                                                break;
                                            }

                                        }


                                    }



                                    //while(1)
                                    //                                {
                                    //                                    bzero(msg, BUFFER_SIZE);
                                    //                                    memcpy(msg, p+2, BUFFER_SIZE);
                                    //                                    //NSLog(@"服务器:%s\n",msg);
                                    //                                    bzero(arr, BUFFER_SIZE);
                                    //                                    //memcpy(arr, p+2, strlen(recv_msg+2));
                                    //                                    if(n < BUFFER_SIZE)
                                    //                                    {
                                    //                                        memcpy(arr, p+2, n);
                                    //                                        arr[BUFFER_SIZE] = '\0';
                                    //                                        NSLog(@"服务器:%s\n",arr)
                                    //                                        NSString *str=[NSString stringWithCString:arr encoding:NSUTF8StringEncoding];
                                    //                                        //NSLog(@"服务器:%d\n",[str length]);
                                    //                                        //NSLog(@"服务器:%@\n",str);
                                    //                                        NSError *error = nil;
                                    //
                                    //                                        NSData *da= [str dataUsingEncoding:NSUTF8StringEncoding];
                                    //                                        NSLog(@"服务器:%d\n",[da length]);
                                    //
                                    //
                                    //                                        NSDictionary * dic =  [NSJSONSerialization JSONObjectWithData:da options:NSJSONReadingMutableLeaves error:&error];
                                    //                                        if(dic != nil)
                                    //                                        {
                                    //                                            NSLog(@"服务器:%@\n",dic);
                                    //                                            NSLog(@"服务器:%d\n",[error code]);
                                    //
                                    //                                            @try
                                    //                                            {
                                    //                                                NSDictionary * dicinfo =  [dic objectForKey:@"head"];
                                    //                                                NSString * s1 =  [dic objectForKey:@"body"];
                                    //                                                NSLog(@"服务器:%@\n",s1);
                                    //                                                NSLog(@"服务器:%@\n",dicinfo);
                                    //                                                //NSDictionary * dicinfo2 =  [dic objectForKey:@"head1"];
                                    //                                                NSString * s2 =  [dic objectForKey:@"bo1"];
                                    //                                                NSLog(@"服务器:%@\n",s2);
                                    //
                                    //                                            }@catch (NSException * e) {
                                    //                                                NSLog(@@"Exception: %@", e);
                                    //
                                    //                                            }
                                    //                                        }
                                    //                                        else
                                    //                                        {
                                    //                                            NSLog(@"服务器:消息格式错误");
                                    //                                        }
                                    //
                                    //                                    }
                                    //                                    else
                                    //                                    {
                                    //
                                    //                                        m = n;
                                    //                                        memcpy(arr, p+2, n);
                                    //                                        arr[BUFFER_SIZE] = '\0';
                                    //                                        NSLog(@"服务器:%s\n",arr)
                                    //                                        str1 = [NSString stringWithCString:arr encoding:NSUTF8StringEncoding];
                                    //                                        bzero(recv_msg, BUFFER_SIZE);
                                    //                                        byte_num = recv(server_sock_fd,recv_msg,BUFFER_SIZE,0);
                                    //                                        while (1)
                                    //                                        {
                                    //                                            p = recv_msg;
                                    //                                            memcpy(arr, p+2, n);
                                    //                                            arr[BUFFER_SIZE] = '\0';
                                    //                                            NSLog(@"服务器:%s\n",arr)
                                    //                                            str2 = [NSString stringWithCString:arr encoding:NSUTF8StringEncoding];
                                    //                                            message = [str1 stringByAppendingString:str2];
                                    //                                            str1 = message;
                                    //                                            if(n == [str1 length])
                                    //                                            {
                                    //
                                    //                                            }
                                    //                                        }
                                    //
                                    //                                    }
                                    //
                                    //
                                    //
                                    //                                    break;
                                    //
                                    //
                                    //
                                    //
                                    //                                }

                                }
                                //[self decodePushMessage:recv_msg:dec:&iStart];

                            }
                            else if(byte_num == 1)
                            {
                                NSLog(@"无法识别的消息!\n");
                            }
                            else if(byte_num < 0)
                            {
                                     NSLog(@"接收消息出错!\n");
                                    //从实际运行上发现,若出现接收消息错误,后面无论如何接收消息都报同样的错误,所以还是关闭SOCKET,重新建立连接吧!
                                    close(server_sock_fd);
                                    goto SKIP;
                            }
                            else{
                                close(server_sock_fd);
                                NSLog(@"服务器端退出!\n");
                                goto SKIP;
                                //exit(0);
                            }

                        }

                        FD_ZERO(&client_fd_set);
                        FD_ZERO(&read_fd_set);
                        FD_SET(server_sock_fd, &client_fd_set);
                        FD_SET(server_sock_fd, &read_fd_set);

                        tv.tv_sec = 1;
                        tv.tv_usec = 0;
                        //socket一般都处于可写状态,除了网卡满了写不进去的罕见情况,所以该处侦听一般都是立刻响应
                        ret = select(server_sock_fd + 1, &read_fd_set, &client_fd_set, NULL, &tv);
                        //[g_puTc lock];
                        if (ret < 0 ) {
                            NSLog(@"select 出错!\n");
                            //[g_puTc unlock];
                            goto SKIP;
                        }
                        else if(ret ==0){
                            NSLog(@"select 超时!\n");
                            //[g_puTc unlock];
                            continue;
                        }
                        else{
                            NSLog(@"ret4= %d\n", ((FD_ISSET(server_sock_fd, &client_fd_set)) && (FD_ISSET(server_sock_fd, &read_fd_set))));
                            i = 10 - tv.tv_sec;
                            NSLog(@"i= %d\n", i);

                            //先把消息接收过来,后面再处理,防止在处理消息时,连接异常。
                            if (FD_ISSET(server_sock_fd, &read_fd_set))
                            {
                                NSLog(@"ret2= %d\n", ret);
                                bzero(recv_msg, BUFFER_SIZE);
                                long byte_num = recv(server_sock_fd,recv_msg,BUFFER_SIZE,0);
                                if (byte_num > 0) {
                                    if (byte_num > BUFFER_SIZE) {
                                        byte_num = BUFFER_SIZE;
                                    }
                                    recv_msg[byte_num] = '\0';
                                    NSLog(@"服务器:%s\n",recv_msg);
                                    handleFlag = YES;
                                }else if(byte_num < 0){
                                    NSLog(@"接受消息出错!\n");
                                }else{
                                    close(server_sock_fd);
                                    NSLog(@"服务器端退出!\n");
                                    goto SKIP;
                                    //exit(0);
                                }

                            }

                            //判断是否可写,若可写,并且有消息可以发送就像服务器推送消息。
                            if (FD_ISSET(server_sock_fd, &client_fd_set)) {
                                bzero(input_msg, BUFFER_SIZE);

                                if((g_LoginShiftState == SHIFT_STATE_INIT) || (g_LoginShiftState == SHIFT_STATE_UNLOGIN))
                                {
                                    bzero(msg, BUFFER_SIZE);
                                    snprintf(msg, sizeof(msg), "#################################################################POSITON latitude = %f, longitude = %f", g_latitude, g_longitude);
                                    bzero(input_msg, BUFFER_SIZE);

                                    snprintf(msg, sizeof(msg), "{\"head\":{\"token\":\"%s\",\"cmd\":\"0002\",\"result\":\"0\",\"ecode\":\"\",\"msg\":\"\"},\"body\":{}}", [g_token UTF8String]);

                                    NSLog(@"msg= %s\n", msg);
                                    len = strlen(msg);
                                    snprintf(input_msg+2, len+1, "%s", msg);
                                    NSUInteger m = 0;
                                    NSUInteger j = 1;
                                    m  = len;
                                    if(m/256 == 0)
                                    {
                                        input_msg[j--] = m % 256;
                                        input_msg[j] = 0;
                                    }
                                    else if(m/65536 == 0)
                                    {
                                        input_msg[j--] = m % 256;
                                        input_msg[j] = m/256;
                                    }
                                    NSLog(@"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@input_msg3=%s\n", input_msg+2);
                                    while (!g_fdWriteFlag)
                                    {
                                        sleep(3);
                                    }
                                    g_fdWriteFlag = NO;
                                    ret = send(server_sock_fd, input_msg, len + 2, 0);
                                    if (ret == -1) {
                                        NSLog(@"发送消息出错!\n");
                                        NSLog(@"ret7= %d\n", ret);
                                        g_fdWriteFlag = YES;
                                        //[g_puTc unlock];
                                        goto SKIP;
                                    }
                                    else
                                    {
                                        if((g_LoginShiftState == SHIFT_STATE_INIT) || (g_LoginShiftState == SHIFT_STATE_UNLOGIN))
                                        {
                                            g_LoginShiftState = SHIFT_STATE_LOGINING;
                                        }
                                        NSLog(@"ret8= %d\n", ret);

                                    }
                                    g_fdWriteFlag = YES;
                                }
                                else if(g_LoginShiftState == SHIFT_STATE_LOGINING)
                                {
                                    curDate = [NSDate date];

                                    NSTimeInterval nowTime = [curDate timeIntervalSince1970]*1;

                                    if(nowTime - g_pushTime >= 15*2)
                                    {
                                        bzero(msg, 300);
                                        snprintf(msg, sizeof(msg), "#################################################################POSITON latitude = %f, longitude = %f", g_latitude, g_longitude);
                                        bzero(input_msg, BUFFER_SIZE);

                                        snprintf(msg, sizeof(msg), "{\"head\":{\"token\":\"%s\",\"cmd\":\"0001\",\"result\":\"0\",\"ecode\":\"\",\"msg\":\"\"},\"body\":{\"latitude\":%f,\"longitude\":%f}}", [g_token UTF8String], g_latitude, g_longitude);

                                        NSLog(@"msg= %s\n", msg);
                                        len = strlen(msg);
                                        snprintf(input_msg+2, len+1, "%s", msg);
                                        NSUInteger m = 0;
                                        NSUInteger j = 1;
                                        m  = len;
                                        if(m/256 == 0)
                                        {
                                            input_msg[j--] = m % 256;
                                            input_msg[j] = 0;
                                        }
                                        else if(m/65536 == 0)
                                        {
                                            input_msg[j--] = m % 256;
                                            input_msg[j] = m/256;
                                        }
                                        NSLog(@"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@input_msg4=%s\n", input_msg+2);
                                        while (!g_fdWriteFlag)
                                        {
                                            sleep(3);
                                        }
                                        g_fdWriteFlag = NO;
                                        ret = send(server_sock_fd, input_msg, len + 2, 0);
                                        if (ret == -1) {
                                            NSLog(@"发送消息出错!\n");
                                            NSLog(@"ret7= %d\n", ret);
                                            g_fdWriteFlag = YES;
                                            //[g_puTc unlock];
                                            goto SKIP;
                                        }
                                        else
                                        {
                                            NSLog(@"ret8= %d\n", ret);
                                            g_pushTime = nowTime;
                                        }
                                        g_fdWriteFlag = YES;
                                    }


                                }

                            }
                            //在此处处理服务器发过来的消息
                            //handleMessage

                            //[g_puTc unlock];

                        }




                    }
                }

            }
            else
            {
                close(server_sock_fd);
                //flag = 1;
                sleep(5);
                goto SKIP;
            }


        }

    });
}

服务端代码:

- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
    [super windowControllerDidLoadNib:aController];

    [_nsT setStringValue:@"set sth."];
    struct sockaddr_in server_addr;
    server_addr.sin_len = sizeof(struct sockaddr_in);
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(9123);
    //server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_addr.s_addr = inet_addr("172.16.28.123");
    bzero(&(server_addr.sin_zero),8);

    char recv_msg[1024];
    char input_msg[BUFFER_SIZE];

    //创建socket
    int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_sock_fd == -1) {
        perror("socket error");
        return;
    }
    //绑定socket
    int bind_result = bind(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (bind_result == -1) {
        perror("bind error");
        return;
    }
    //listen
    if (listen(server_sock_fd, BACKLOG) == -1) {
        perror("listen error");
        return;
    }
    int kq = kqueue();
    if (kq == -1) {
        perror("创建kqueue出错!\n");
        exit(1);
    }
    struct kevent event_change;
    EV_SET(&event_change, STDIN_FILENO, EVFILT_READ, EV_ADD, 0, 0, NULL);
    kevent(kq, &event_change, 1, NULL, 0, NULL);
    EV_SET(&event_change, server_sock_fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
    kevent(kq, &event_change, 1, NULL, 0, NULL);
    while (1) {
        struct timespec timeout = {10,0};
        int ret = kevent(kq, NULL, 0, events, 10, &timeout);
        if (ret < 0) {
            printf("kevent 出错!\n");
            continue;
        }else if(ret == 0){
            printf("kenvent 超时!\n");
            continue;
        }else{
            //ret > 0 返回事件放在events中
            for (int i = 0; i < ret; i++) {
                struct kevent current_event = events[i];
                //kevent中的ident就是文件描述符
                if (current_event.ident == STDIN_FILENO) {
                    //标准输入
                    bzero(input_msg, BUFFER_SIZE);
                    fgets(input_msg, BUFFER_SIZE, stdin);
                    //输入 ".quit" 则退出服务器
                    if (strcmp(input_msg, QUIT_CMD) == 0) {
                        exit(0);
                    }
                    for (int i=0; i<CONCURRENT_MAX; i++) {
                        if (client_fds[i]!=0) {
                            send(client_fds[i], input_msg, BUFFER_SIZE, 0);
                        }
                    }
                }else if(current_event.ident == server_sock_fd){
                    //有新的连接请求
                    struct sockaddr_in client_address;
                    socklen_t address_len;
                    int client_socket_fd = accept(server_sock_fd, (struct sockaddr *)&client_address, &address_len);
                    if (client_socket_fd > 0) {
                        int index = -1;
                        for (int i = 0; i < CONCURRENT_MAX; i++) {
                            if (client_fds[i] == 0) {
                                index = i;
                                client_fds[i] = client_socket_fd;
                                break;
                            }
                        }
                        if (index >= 0) {
                            EV_SET(&event_change, client_socket_fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
                            kevent(kq, &event_change, 1, NULL, 0, NULL);
                            printf("新客户端(fd = %d)加入成功 %s:%d \n",client_socket_fd,inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
                        }else{
                            bzero(input_msg, BUFFER_SIZE);
                            strcpy(input_msg, "服务器加入的客户端数达到最大值,无法加入!\n");
                            send(client_socket_fd, input_msg, BUFFER_SIZE, 0);
                            printf("客户端连接数达到最大值,新客户端加入失败 %s:%d \n",inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
                        }
                    }
                }else{
                    //处理某个客户端过来的消息
                    bzero(recv_msg, BUFFER_SIZE);
                    long byte_num = recv((int)current_event.ident,recv_msg,BUFFER_SIZE,0);
                    if (byte_num > 0) {
                        if (byte_num > BUFFER_SIZE) {
                            byte_num = BUFFER_SIZE;
                        }
                        recv_msg[byte_num] = '\0';
                        printf("客户端(fd = %d):%s\n",(int)current_event.ident,recv_msg);
                        //sleep(3);
                        bzero(input_msg, BUFFER_SIZE);
                        strcpy(input_msg, "123454678!\n");
                        if(send((int)current_event.ident, input_msg, BUFFER_SIZE, 0) == -1)
                        {
                             perror("send error");
                        }
                        else
                        {
                            printf("input_msg%s\n", input_msg);
                        }

                        //printf("input_msg %s:%d \n",inet_ntoa(((int)current_event.ident).sin_addr),ntohs(((int)current_event.ident).sin_port));

                    }else if(byte_num < 0){
                        printf("从客户端(fd = %d)接受消息出错.\n",(int)current_event.ident);
                    }else{
                        EV_SET(&event_change, current_event.ident, EVFILT_READ, EV_DELETE, 0, 0, NULL);
                        kevent(kq, &event_change, 1, NULL, 0, NULL);
                        close((int)current_event.ident);
                        for (int i = 0; i < CONCURRENT_MAX; i++) {
                            if (client_fds[i] == (int)current_event.ident) {
                                client_fds[i] = 0;
                                break;
                            }
                        }
                        printf("客户端(fd = %d)退出了\n",(int)current_event.ident);
                    }
                }
            }
        }
    }

     // Add any code here that needs to be executed once the windowController has loaded the document's window.
}
目录
相关文章
|
3月前
|
网络协议 安全 网络安全
网络编程:基于socket的TCP/IP通信。
网络编程:基于socket的TCP/IP通信。
230 0
|
1月前
|
Python
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
使用Python的socket库实现客户端到服务器端的图片传输,包括客户端和服务器端的代码实现,以及传输结果的展示。
129 3
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
|
1月前
|
JSON 数据格式 Python
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
本文介绍了如何使用Python的socket模块实现客户端到服务器端的文件传输,包括客户端发送文件信息和内容,服务器端接收并保存文件的完整过程。
135 1
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
|
30天前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【10月更文挑战第10天】网络协议定义了机器间通信的标准格式,确保信息准确无损地传输。主要分为两种模型:OSI七层模型与TCP/IP模型。
|
2月前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【9月更文挑战第14天】网络协议是机器间交流的约定格式,确保信息准确传达。主要模型有OSI七层与TCP/IP模型,通过分层简化复杂网络环境。IP地址全局定位设备,MAC地址则在本地网络中定位。网络分层后,数据包层层封装,经由不同层次协议处理,最终通过Socket系统调用在应用层解析和响应。
|
3月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
113 0
|
1月前
|
网络协议 测试技术 网络安全
Python编程-Socket网络编程
Python编程-Socket网络编程
|
4月前
|
网络协议 开发者 Python
深度探索Python Socket编程:从理论到实践,进阶篇带你领略网络编程的魅力!
【7月更文挑战第25天】在网络编程中, Python Socket编程因灵活性强而广受青睐。本文采用问答形式深入探讨其进阶技巧。**问题一**: Socket编程基于TCP/IP,通过创建Socket对象实现通信,支持客户端和服务器间的数据交换。**问题二**: 提升并发处理能力的方法包括多线程(适用于I/O密集型任务)、多进程(绕过GIL限制)和异步IO(asyncio)。**问题三**: 提供了一个使用asyncio库实现的异步Socket服务器示例,展示如何接收及响应客户端消息。通过这些内容,希望能激发读者对网络编程的兴趣并引导进一步探索。
55 4
|
4月前
|
开发者 Python
Python Socket编程:不只是基础,更有进阶秘籍,让你的网络应用飞起来!
【7月更文挑战第25天】在网络应用蓬勃发展的数字时代,Python凭借其简洁的语法和强大的库支持成为开发高效应用的首选。本文通过实时聊天室案例,介绍了Python Socket编程的基础与进阶技巧,包括服务器与客户端的建立、数据交换等基础篇内容,以及使用多线程和异步IO提升性能的进阶篇。基础示例展示了服务器端监听连接请求、接收转发消息,客户端连接服务器并收发消息的过程。进阶部分讨论了如何利用Python的`threading`模块和`asyncio`库来处理多客户端连接,提高应用的并发处理能力和响应速度。掌握这些技能,能使开发者在网络编程领域更加游刃有余,构建出高性能的应用程序。
33 3
|
4月前
|
网络协议 Python
网络世界的建筑师:Python Socket编程基础与进阶,构建你的网络帝国!
【7月更文挑战第26天】在网络的数字宇宙中,Python Socket编程是开启网络世界大门的钥匙。本指南将引领你从基础到实战,成为网络世界的建筑师。
64 2