码迷,mamicode.com
首页 > 其他好文 > 详细

socket心跳+聊天

时间:2015-06-18 08:12:20      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:

简单的小程序,vs2015编译通过

server

#include <tchar.h>
#include <winsock2.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")
#define PORT 2000 //端口号

typedef struct                    /* message structure */
{
    UINT16 type;
    char data[1024];
} msg_t;

#define MSG_TYPE1        1        /* application specific msg */
#define MSG_TYPE2        2        /* another one */
#define MSG_HEARTBEAT    3        /* heartbeat message */

#define T1        60        /* idle time before heartbeat */
#define T2        10        /* time to wait for response */
int _tmain(int argc, _TCHAR* argv[])
{
    WSADATA wsa;
    //初始化套接字DLL
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    {
        printf("套接字初始化失败!");
        exit(-1);
    }

    SOCKET serverSocket;
    if ((serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
    {
        printf("创建套接字失败!");
        exit(-1);
    }
    struct sockaddr_in serverAddress;
    memset(&serverAddress, 0, sizeof(sockaddr_in));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    serverAddress.sin_port = htons(PORT);

    if (bind(serverSocket, (sockaddr*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR)
    {
        printf("套接字绑定到端口失败!端口: %d\n", PORT);
        return -1;
    }
    //进入侦听状态
    if (listen(serverSocket, SOMAXCONN) == SOCKET_ERROR)
    {
        printf("侦听失败!");
        return -1;
    }

    printf("服务器端口: %d 正在监听......\n", PORT);
    //非阻塞
    ULONG nonblock = 1;
    if (ioctlsocket(serverSocket, FIONBIO, &nonblock) == SOCKET_ERROR)
    {
        printf("ioctlsocket() failed with error %d\n", WSAGetLastError());
        return -1;
    }
    SOCKET acceptSocket;//用来和客户端通信的套接字
    struct sockaddr_in clientAddress;//用来和客户端通信的套接字地址
    memset(&clientAddress, 0, sizeof(clientAddress));
    int addrlen = sizeof(clientAddress);

    //fd_set fdRead;
    fd_set fdSocket;
    FD_ZERO(&fdSocket);
    FD_SET(serverSocket, &fdSocket);

    struct timeval tv;
    tv.tv_sec = T1 + T2;
    tv.tv_usec = 0;
    int missed_heartbeats = 0;


    msg_t msg;

    while (true)
    {
        fd_set fdRead = fdSocket;
        int nRet = select(serverSocket + 1, &fdRead, NULL, NULL, &tv);
        if (nRet < 0)
        {
            printf("select失败\n");
            break;
        }
        if (nRet == 0)        /* timed out */
        {
            if (++missed_heartbeats > 3)
                printf("连续三个心跳未收到,可能服务器已挂\n");
            printf("心跳未收到 #%d\n", missed_heartbeats);
            tv.tv_sec = T2;
            continue;
        }
        else
        {
            for (int i = 0; i < (int)fdSocket.fd_count; i++)
            {
                if (FD_ISSET(fdSocket.fd_array[i], &fdRead))
                {
                    if (fdSocket.fd_array[i] == serverSocket)
                    {
                        if ((acceptSocket = accept(serverSocket, (sockaddr*)&clientAddress, &addrlen)) == INVALID_SOCKET)
                        {
                            printf("接受客户端连接失败!");
                            return -1;
                        }
                        ULONG nonblock = 1;
                        if (ioctlsocket(acceptSocket, FIONBIO, &nonblock) == SOCKET_ERROR)
                        {
                            printf("Socket异步配置错误 %d\n", WSAGetLastError());
                            return -1;
                        }
                        FD_SET(acceptSocket, &fdSocket);
                        printf("建立连接成功\n");
                    }
                    else
                    {
                        //nRet--;
                        acceptSocket = fdSocket.fd_array[i];
                        //char buf[1024];
                        //int cnt=sizeof(buf);
                        memset(&msg, 0, sizeof(msg));
                        int bytes;
                        //if ((bytes = recv(acceptSocket, buf, 2, 0)) == SOCKET_ERROR)

                        if ((bytes = recv(acceptSocket, (char *)&msg, sizeof(msg), 0)) == SOCKET_ERROR)
                        {
                            printf("接收数据失败!\n");
                            return -1;
                        }
                        if (bytes > 0)
                        {
                            switch (ntohs(msg.type))
                            {
                            case MSG_TYPE1:
                            case MSG_TYPE2:
                                printf("有消息来自 %s: %s\n", inet_ntoa(clientAddress.sin_addr), msg.data);
                                if (send(acceptSocket, (char *)& msg, sizeof(msg_t), 0) == SOCKET_ERROR)
                                {
                                    printf("发送数据失败!");
                                    return -1;
                                }
                                missed_heartbeats = 0;
                                tv.tv_sec = T1 + T2;
                                break;
                            case MSG_HEARTBEAT:
                                printf("收到心跳\n");
                                bytes = send(acceptSocket, (char *)&msg, sizeof(msg), 0);
                                if (bytes < 0)
                                {
                                    printf("心跳回送失败\n");
                                    return -1;
                                }
                                missed_heartbeats = 0;
                                tv.tv_sec = T1 + T2;
                                break;
                            default:
                                printf("未知类型\n");
                                closesocket(fdSocket.fd_array[i]);
                                FD_CLR(fdSocket.fd_array[i], &fdSocket);
                                break;
                            }
                        }
                        else
                        {
                            closesocket(fdSocket.fd_array[i]);
                            FD_CLR(fdSocket.fd_array[i], &fdSocket);
                        }
                    }
                }
            }
        }
    }
    //清理套接字占用的资源
    WSACleanup();
    return 0;
}

client

#include <tchar.h>
#include <winsock2.h>
#include <stdio.h>
#include <windows.h>
#include <process.h>
#pragma comment(lib,"ws2_32.lib")
#define  PORT 2000

typedef struct                    /* message structure */
{
    UINT16 type;
    char data[1024];
} msg_t;

#define MSG_TYPE1        1        /* application specific msg */
#define MSG_TYPE2        2        /* another one */
#define MSG_HEARTBEAT    3        /* heartbeat message */

#define T1        6        /* idle time before heartbeat */
#define T2        1        /* time to wait for response */

DWORD WINAPI listenFunc(PVOID pvParam) {
    SOCKET sock = *((SOCKET*)pvParam);
    fd_set fdSocket;
    FD_ZERO(&fdSocket);
    FD_SET(sock, &fdSocket);
    struct timeval tv;
    tv.tv_sec = T1;
    tv.tv_usec = 0;
    int missed_heartbeats = 0;
    msg_t msg;
    int length;
    while (1)
    {
        fd_set fdRead = fdSocket;
        int nRet = select(sock + 1, &fdRead, NULL, NULL, &tv);
        if (nRet == 0)        /* timed out */
        {
            if (++missed_heartbeats > 3)
            {
                printf("连续三个心跳未收到,可能服务器已挂\n");
            }
            printf("发送心跳 #%d\n", missed_heartbeats);
            msg.type = htons(MSG_HEARTBEAT);
            if (send(sock, (char*)&msg, sizeof(msg), 0) == SOCKET_ERROR)
            {
                printf("发送数据失败!");
                return -1;
            }
            tv.tv_sec = T2;
            continue;
        }
        else
        {
            memset(&msg, 0, sizeof(msg));
            int bytes;
            if ((bytes = recv(sock, (char *)&msg, sizeof(msg), 0)) == SOCKET_ERROR)
            {
                printf("接收数据失败!\n");
                return -1;
            }
            if (bytes > 0)
            {
                switch (ntohs(msg.type))
                {
                case MSG_TYPE1:
                case MSG_TYPE2:
                    printf("有消息来: %s\n", msg.data);
                    break;
                case MSG_HEARTBEAT:
                    printf("收到心跳\n");
                    break;
                default:
                    printf("未知类型\n");
                    closesocket(sock);
                    FD_CLR(sock, &fdSocket);
                    break;
                }
                missed_heartbeats = 0;
                tv.tv_sec = T1 + T2;
            }
            else
            {
                closesocket(sock);
                FD_CLR(sock, &fdSocket);
            }
        }
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    WSADATA wsa;
    //初始化套接字DLL
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    {
        printf("套接字初始化失败!");
        return -1;
    }

    SOCKET sock;
    if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
    {
        printf("创建套接字失败!");
        return -1;
    }
    //char ipaddr[100];
    //printf("请输入对方ip地址:");
    //gets(ipaddr);
    struct sockaddr_in serverAddress;
    memset(&serverAddress, 0, sizeof(sockaddr_in));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    serverAddress.sin_port = htons(PORT);

    if (connect(sock, (sockaddr*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR)
    {
        printf("建立连接失败!");
        return -1;
    }

    ULONG nonblock = 1;
    if (ioctlsocket(sock, FIONBIO, &nonblock) == SOCKET_ERROR)
    {
        printf("ioctlsocket() failed with error %d\n", WSAGetLastError());
        return -1;
    }

    _beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void *))listenFunc, &sock, 0, NULL);

    msg_t msg;
    memset(&msg, 0, sizeof(msg));

    while (true)
    {
        gets_s(msg.data);
        msg.type = htons(MSG_TYPE1);
        if (send(sock, (char*)&msg, sizeof(msg), 0) == SOCKET_ERROR)
        {
            printf("发送数据失败!");
            return -1;
        }
    }
    //清理套接字占用的资源
    WSACleanup();
    return 0;
}

 

socket心跳+聊天

标签:

原文地址:http://www.cnblogs.com/leisurely/p/4584786.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!