Linux TCP服务器和客户端函数

my_socket.c:

#include "my_socket.h"

int createTcpClient(const int serPort, const char* serIp)
{
    int                serFd = -1;
    int                ret;
    struct sockaddr_in saddr;

    serFd = socket(PF_INET, SOCK_STREAM, 0);
    if (serFd < 0)
    {
        perror("socket");
        return -1;
    }

    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(serPort);
    inet_pton(AF_INET, serIp, &saddr.sin_addr.s_addr);

    ret = connect(serFd, (struct sockaddr*)&saddr, sizeof(saddr));
    if (ret < 0)
    {
        perror("connect");
        if (serFd > 0)
        {
            close(serFd);
        }
        return -1;
    }
    return serFd;
}

int createTcpServer(const int serPort)
{
    int                serFd;
    struct sockaddr_in serAddr;
    struct sockaddr_in cliAddr;
    int                addrLen = sizeof(cliAddr);
    int                cliFd = -1;
    char               buffer[4096];
    int                iDataNum;
    int                ret = -1;
    if ((serFd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket");
        return 1;
    }

    bzero(&serAddr, sizeof(serAddr));
    //初始化服务器端的套接字,并用htons和htonl将端口和地址转成网络字节序
    serAddr.sin_family = AF_INET;
    serAddr.sin_port = htons(serPort);
    // ip可是是本服务器的ip,也可以用宏INADDR_ANY代替,代表0.0.0.0,表明所有地址
    serAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    //对于bind,accept之类的函数,里面套接字参数都是需要强制转换成(struct sockaddr
    //*) bind三个参数:服务器端的套接字的文件描述符,
    int opt = 1;
    setsockopt(serFd, SOL_SOCKET, SO_REUSEADDR, (const void*)&opt, sizeof(opt));
    if (bind(serFd, (struct sockaddr*)&serAddr, sizeof(serAddr)) < 0)
    {
        perror("connect");
        return 1;
    }
    //设置服务器上的socket为监听状态
    if (listen(serFd, 5) < 0)
    {
        perror("listen");
        return 1;
    }

    printf("Listening on port: %d\n", serPort);

    fd_set serSet, rserSet;
    FD_ZERO(&serSet);
    FD_SET(serFd, &serSet);

    int            maxfd = serFd;
    struct timeval tv0;
    while (1)
    {
        rserSet = serSet;
        printf("wait select ....\n");
        tv0.tv_sec = 5;
        tv0.tv_usec = 0;
        ret = select(maxfd + 1, &rserSet, NULL, NULL,&tv0);  //对读进行操作等待(NULL时无限等待)

        if (ret == 0)
        {
            printf("select ret == 0 ....\n");
            continue;
        }
        if (ret < 0)
        {
            perror("select");
            sleep(1);
            continue;
        }
        if (FD_ISSET(serFd, &rserSet))
        {
            if (cliFd > 0)
            {
                printf("client(IP:%s port:%d) is broken ...\n",inet_ntoa(cliAddr.sin_addr),htons(cliAddr.sin_port));
                close(cliFd);
                cliFd = -1;
            }
            cliFd = accept(serFd, (struct sockaddr*)&cliAddr, (socklen_t*)&addrLen);
            if (cliFd < 0)
            {
                perror("accept");
                continue;
            }
            printf("\nrecv cliFd data...\n");
            // inet_ntoa   ip地址转换函数,将网络字节序IP转换为点分十进制IP
            //表达式:char *inet_ntoa (struct in_addr);
            printf("client(IP:%s port:%d) connect ...\n",inet_ntoa(cliAddr.sin_addr),htons(cliAddr.sin_port));
            if (cliFd > maxfd)
            {
                maxfd = cliFd;
            }
            FD_SET(cliFd, &serSet);
        }
        else
        {
            if (cliFd < 0)
            {
                continue;
            }
            memset(buffer, 0, 4096);
            iDataNum = recv(cliFd, buffer, 4096, MSG_DONTWAIT);
            if (iDataNum <= 0)
            {
                FD_CLR(cliFd, &serSet);

                if (iDataNum < 0)
                {
                    perror("recv");
                }
                else
                {
                    if (cliFd > 0)
                    {
                        printf("client(IP:%s port:%d) disconnect ...\n",inet_ntoa(cliAddr.sin_addr),htons(cliAddr.sin_port));
                        close(cliFd);
                    }
                    cliFd = -1;
                }
                continue;
            }
            else
            {
                printf("buffer form cli: %s\n", buffer);
            }
        }
    }
    if(serFd > 0)close(serFd);
    if(cliFd > 0)close(cliFd);
    return 0;
}

ser.c:

#include "my_socket.h"

int main()
{
    createTcpServer(8888);
}

 

cli.c:

#include "my_socket.h"

int main()
{
    int  serFd = createTcpClient(8888, "127.0.0.1");
    char buf[] = "abcdefg";
    int  ret = -1;
    while (1)
    {
        ret = send(serFd, buf, sizeof(buf), 0);
        if (ret < 0)
        {
            perror("send");
            break;
        }
        sleep(1);
    }
    if(serFd > 0)close(serFd);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值