TCP/IP协议源码(加入了select的IO复用)

该代码示例展示了如何在Windows环境下使用Winsock进行网络编程,包括错误处理函数printMsg_WSAGetLastError(),获取本地和对端套接字地址的函数,以及使用select进行并发I/O操作的线程函数threadIoSelect()。程序创建了一个监听套接字,并等待客户端连接,同时处理接收和发送数据。
摘要由CSDN通过智能技术生成

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")

/*--------------------------------------------------------------------------*/
#define MAX_MSG_SIZE 1024

char  bSendBuf[1500];
char  bRcvBuf[1500];
struct sockaddr_in gSvrSocketAddr;
fd_set gsReadFdSet;

/*--------------------------------------------------------------------------*/
void printMsg_WSAGetLastError()//错误处理
{
    LPVOID lpMsgBuf;
    int nErrorCode;

    nErrorCode = WSAGetLastError();//报错处理
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        nErrorCode,
        0, //Language Identifiers 0x0804, // zh-ch:0x0804,en-us:0x0409,
        (LPTSTR)&lpMsgBuf,
        0,
        NULL
    );
    printf("WSAGetLastError()=%d, %s\n", nErrorCode, lpMsgBuf);
    LocalFree(lpMsgBuf);
}
/*--------------------------------------------------------------------------*/
int bzygetLocalSocketAddrName(int socketFd)//获取本地socket地址 
{
    struct sockaddr_in SocketAddr;
    int nLen;
    int nRet;

    memset(&SocketAddr, 0, sizeof(struct sockaddr_in));
    nLen = sizeof(struct sockaddr_in);
    nRet = getsockname(socketFd, (SOCKADDR*)&SocketAddr, &nLen);
    if (0 == nRet)
    {
        printf("socketfd=%d local[ip=%d.%d.%d.%d,port=%d]\n",
            socketFd,
            *((BYTE*)&SocketAddr.sin_addr),
            *((BYTE*)&SocketAddr.sin_addr + 1),
            *((BYTE*)&SocketAddr.sin_addr + 2),
            *((BYTE*)&SocketAddr.sin_addr + 3),
            ntohs(SocketAddr.sin_port));
        return 0;
    }
    else
    {
        printf("socketfd=%d,getsockname failure: ", socketFd);
        printMsg_WSAGetLastError();
        return -1;
    }
}
/*--------------------------------------------------------------------------*/
int bzygetPeerSocketAddrName(int socketFd)//获取对端socket地址 
{
    struct sockaddr_in SocketAddr;
    int nLen;
    int nRet;

    memset(&SocketAddr, 0, sizeof(struct sockaddr_in));
    nLen = sizeof(struct sockaddr_in);
    nRet = getpeername(socketFd, (SOCKADDR*)&SocketAddr, &nLen);
    if (0 == nRet)
    {
        printf("socketfd=%d peer[ip=%d.%d.%d.%d,port=%d]\n",
            socketFd,
            *((BYTE*)&SocketAddr.sin_addr),
            *((BYTE*)&SocketAddr.sin_addr + 1),
            *((BYTE*)&SocketAddr.sin_addr + 2),
            *((BYTE*)&SocketAddr.sin_addr + 3),
            ntohs(SocketAddr.sin_port));
        return 0;
    }
    else
    {
        printf("socketfd=%d,getpeername failure: ", socketFd);
        printMsg_WSAGetLastError();
        return -1;
    }
}
/*--------------------------------------------------------------------------*/
int WINAPI threadIoSelect(LPVOID lpParam)//建立select并发 
{
    fd_set readFdSet;
    int listenSocketFd;
    int dataSocketFd;
    int nBytesRead;
    int nRetcode;
    int fd;
    int i;

    listenSocketFd = (int)lpParam;
    while (1)
    {
        FD_ZERO(&readFdSet);

        readFdSet = gsReadFdSet;

        printf("select input fdset : ");
        for (i = 0; i < readFdSet.fd_count; i++)
        {
            fd = readFdSet.fd_array[i];
            printf("%d ", fd);
        }
        printf("\n");

        nRetcode = select(0, &readFdSet, NULL, NULL, NULL);//创建select IO复用,接收消息提升
        if (0 == nRetcode)
        {
            continue;
        }
        if (0 > nRetcode)
        {
            printf("select failure: ");
            printMsg_WSAGetLastError();
            break;
        }

        printf("select output fdset : ");
        for (i = 0; i < readFdSet.fd_count; i++)
        {
            fd = readFdSet.fd_array[i];
            printf("%d ", fd);
        }
        printf("\n");

        for (i = 0; i < readFdSet.fd_count; i++)
        {
            fd = readFdSet.fd_array[i];
            if (fd == listenSocketFd)
            {
                //listen socket fd
                dataSocketFd = accept(listenSocketFd, NULL, NULL);//non-block
                if (dataSocketFd <= 0)
                {
                    printf("socketfd=%d,accept failure: ", listenSocketFd);
                    printMsg_WSAGetLastError();

                    FD_CLR(listenSocketFd, &gsReadFdSet);
                    continue;
                }
                else
                {
                    printf("listenSocketFd=%d accept success, new client coming socketfd=%d\n", listenSocketFd, dataSocketFd);
                    bzygetLocalSocketAddrName(dataSocketFd);
                    bzygetPeerSocketAddrName(dataSocketFd);
                    FD_SET(dataSocketFd, &gsReadFdSet);
                }
            }
            else
            {
                //data socket fd
                memset(bRcvBuf, 0, 1500);
                nBytesRead = recv(fd, bRcvBuf, MAX_MSG_SIZE, 0);//进行接收
                if (0 >= nBytesRead)
                {
                    printf("socketfd=%d:data socket error,close\n", fd);
                    printMsg_WSAGetLastError();

                    FD_CLR(fd, &gsReadFdSet);
                    closesocket(fd);

                    continue;
                }
                else
                {
                    bzygetLocalSocketAddrName(fd);
                    bzygetPeerSocketAddrName(fd);
                    printf("socketfd=%d, recv msglen=%d, msg=", fd, nBytesRead);
                    printf("%s\n", bRcvBuf);
                }
            }
        }

    }

    return 0;
}
/*--------------------------------------------------------------------------*/

int main()
{

    WORD wVersionRequested;
    WSADATA wsaData;
    int bzyRetCode;
    int bzysocketfd = -1;
    int nSendDataFd;
    int bzyBytesTx;
    char c;

    wVersionRequested = 0x0202;
    bzyRetCode = WSAStartup(wVersionRequested, &wsaData);//创建网络库
    if (bzyRetCode != 0)
    {
        printf("WSAStartup failed with error: %d\n", bzyRetCode);
        return -1;
    }
    else
    {
        printf("WSAStartup sucess to startup\n");
    }
    if (wsaData.wVersion != wVersionRequested)
    {
        printf("requied wVersion=0x%04x,returned wVersion=0x%04x,returned HighestVersion=0x%04x\n",
            wVersionRequested,
            wsaData.wVersion,
            wsaData.wHighVersion);
        WSACleanup();
        return -1;
    }

    bzysocketfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//创建套接字
    if (bzysocketfd < 0)
    {
        printf("socket create failure,reason:\n");
        printMsg_WSAGetLastError();

        WSACleanup();
        return -1;
    }
    else
    {
        printf("socket create success,socketfd=%d\n", bzysocketfd);
    }

    memset(&gSvrSocketAddr, 0, sizeof(struct sockaddr_in));
    gSvrSocketAddr.sin_family = AF_INET;
    gSvrSocketAddr.sin_port = htons(1423);
    gSvrSocketAddr.sin_addr.s_addr = inet_addr("192.168.43.66");
    bzyRetCode = bind(bzysocketfd, (SOCKADDR*)&gSvrSocketAddr, sizeof(SOCKADDR));//绑定
    if (0 != bzyRetCode)
    {
        printf("socket bind failure,reason:\n");
        printMsg_WSAGetLastError();

        closesocket(bzysocketfd);
        WSACleanup();
        return -1;
    }
    else
    {
        printf("socket bind success\n");
    }

    bzyRetCode = listen(bzysocketfd, SOMAXCONN);
    if (0 != bzyRetCode)
    {
        printf("socket listen failure,reason:\n");
        printMsg_WSAGetLastError();

        closesocket(bzysocketfd);
        WSACleanup();
        return -1;
    }

    //memset(&gsReadFdSet, 0, sizeof(fd_set));
    FD_ZERO(&gsReadFdSet);//清空socketfd

    FD_SET(bzysocketfd, &gsReadFdSet);//设置socketfd

    CreateThread((LPSECURITY_ATTRIBUTES)NULL,
        0,
        (LPTHREAD_START_ROUTINE)threadIoSelect,
        (LPVOID)bzysocketfd,
        0, NULL);
    printf("create thread: threadIoSelect\n");

    Sleep(1000);

    //c = getchar();
    while (1)
    {
        fflush(stdin);
        c = getchar();

        printf("please input client(socketfd) you want to send:\n");
        scanf("%d", &nSendDataFd);

        printf("please input msg you want to send:\n");
        memset(bSendBuf, 0, 1500);
        scanf("%s", bSendBuf);

        bzyBytesTx = send(nSendDataFd, bSendBuf, strlen(bSendBuf), 0);//主函数作为发送 
        if (0 >= bzyBytesTx)
        {
            printf("socketfd=%d send failure,reason:\n", nSendDataFd);
            printMsg_WSAGetLastError();
        }
        else
        {
            printf("socketfd=%d: send msglen=%d\n", nSendDataFd, bzyBytesTx);
        }

    }

    WSACleanup();

    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值