多线程服务器

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>//包含soocket.h
#include<pthread.h>

#define MAX_NUM 10

//信息结构体
struct SockInfo
{
    struct sockaddr_in addr;
    int fd;
};

struct SockInfo infos[MAX_NUM];

void *working(void *arg);

int main()
{
    //1.创建监听的套接字
    int fd=socket(AF_INET,SOCK_STREAM,0);//AF_INET是ipv4,sock_stream是流式协议
    if(fd == -1)
    {
        perror("socket");
        return -1;
    }

    //2.绑定本地的IP port
    struct sockaddr_in saddr;
    saddr.sin_family=AF_INET;
    saddr.sin_port=htons(9999);//转换为大端,主机字节序转换为网络字节序
    saddr.sin_addr.s_addr=INADDR_ANY;//读取本地网卡的ip地址
    int ret=bind(fd,(struct sockaddr*)&saddr,sizeof(saddr));
    if(ret==-1)
    {
        perror("bind");
        return -1;
    }

    //3.设置监听
    ret=listen(fd,128);
    if(ret == -1)
    {
        perror("listen");
        return -1;
    }

    //初始化结构体数组
    int max=sizeof(infos)/sizeof(infos[0]);
    for(int i=0;i<max;i++)
    {
        bzero(&infos[i],sizeof(infos[i]));
        infos[i].fd=-1;//套接字状态默认为-1,用来判断哪个fd是空闲的
    }

    //4.阻塞并等待客户端的连接
    int addrlen=sizeof(struct sockaddr_in);
    while(1)
    {
        struct SockInfo* pinfo;
        for(int i=0;i<max;i++)
        {
            if(infos[i].fd==-1)
            {
                pinfo=&infos[i];
                break;
            }
        }
        int cfd=accept(fd,(struct sockaddr*)&pinfo->addr,&addrlen);
        pinfo->fd=cfd;
        if(cfd == -1)
        {
            perror("accept");
            return -1;
        }
        //创建子线程
        pthread_t tid;
        pthread_create(&tid,NULL,working,pinfo);
        pthread_detach(tid);
    }
    close(fd);

    return 0;
}

void *working(void *arg)
{
    struct SockInfo* pinfo=(struct SockInfo*)arg;

    //连接建立成功,打印客户端的IP地址及端口信息
    char ip[32];
    printf("客户端的IP:%s,端口:%d\n",
            inet_ntop(AF_INET,&pinfo->addr.sin_addr.s_addr,ip,sizeof(ip))
            ,ntohs(pinfo->addr.sin_port));//inet_ntop 大端转小端;ntohs 网络字节序转主机字节序

    //5.通信
    while(1)
    {
        //接受数据
        char buff[1024];
        int len=recv(pinfo->fd,buff,sizeof(buff),0);
        if(len > 0)
        {
            printf("client say: %s\n",buff);
            send(pinfo->fd,buff,len,0);
        }
        else if(len == 0)
        {
            printf("客户端已经断开连接。。。\n");
            break;
        }
        else
        {
            perror("recv");
            break;
        }
    }

    //关闭文件描述符
    close(pinfo->fd);
    pinfo->fd=-1;
    

    return NULL;    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值