网络编程4.20

本文详细描述了一个使用C++编写的简单在线聊天服务器和客户端程序,涉及socket编程,包括创建套接字、绑定、监听、接受连接以及数据传输等关键步骤。
摘要由CSDN通过智能技术生成

在线聊天:

服务器端:

#include<myhead.h>
typedef struct mess{
    char flag;
    char name[20];
    char message[128];
}mess;
typedef struct  fds
{
    char name[20];
    struct sockaddr_in cin;
}fds_t;
int main(int argc, char const *argv[])
{
    char const *IP=argv[1];
    char const *PORT=argv[2];
    int P=atoi(PORT);
    int sfd=socket(AF_INET,SOCK_STREAM,0);//创建套接字
    if(sfd==-1)
    {
        perror("scoket:");
        return -1;
    }
    struct sockaddr_in sin;//填充结构体信息,本机IP和端口号。用于服务器端绑定
    sin.sin_addr.s_addr=inet_addr(IP);
    sin.sin_family=AF_INET;
    sin.sin_port=htons(P); 
    if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)//绑定结构体信息
    {
        perror("bind:");
        return -1;
    }
    int reuse = 1;
    if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))==-1)
    {
        perror("setsockopt error");
        return -1;
    }
    if(listen(sfd,128)==-1)//启动监听
    {
        perror("listen:");
        return -1;
    }
    char buf[128]="";
    fd_set temps,reads;
    int max=sfd;
    int newsfd;
    fds_t  fds[1024];
    struct sockaddr_in temp;
    int len=sizeof(temp);
    FD_ZERO(&temps);
    FD_ZERO(&temps);
    FD_SET(0,&temps);
    FD_SET(sfd,&temps);
    while (1)
    {
        reads=temps;
        int re=select(max+1,&reads,NULL,NULL,NULL);//阻塞等待标识符发生对应的事件,当事件发生时只保留对应的标识符
        if(re==-1)
        {
            perror("select:");
            return -1;
        }
        for(int k=0;k<=max;k++)//循环判断对应哪个标识符存在,再让存在的标识符找对应的事件。
        {
            if(FD_ISSET(k,&reads))
            {
                if(k==0)
                {
                    scanf("%s",buf);
                    mess t;
                    strcpy(t.message,buf);
                    t.flag=2;
                    for(int i=4;i<=max;i++)
                    {
                        write(i,&t,sizeof(t));
                    }
                }
            
            else if(k==sfd)
            {
                newsfd=accept(sfd,(struct sockaddr*)&temp,&len);
                if(newsfd==-1)
                {
                    perror("accept:");
                    return -1;
                }
                char n[20];
                bzero(n,20);
                read(newsfd,n,20);
                printf("[%s:%d]%s登录成功\n",inet_ntoa(temp.sin_addr),ntohs(temp.sin_port),n);                
                FD_SET(newsfd,&temps);
                fds[newsfd].cin=temp;
                mess l;
                l.flag=1;
                strcpy(l.name,n);
                strcpy(fds[newsfd].name,n);                                                                                                                                                                  
                max=max>newsfd?max:newsfd;
                for(int i=4;i<=max;i++)
                {
                    if(i!=newsfd)
                    {
                        write(i,&l,sizeof(l));
                    }
                }
            }
            else
            {
                mess m3;
                bzero(&m3,sizeof(m3));
                read(k,&m3,sizeof(m3));
                if(m3.flag==4)
                {
                    printf("[%s:%d]%s退出登录\n",inet_ntoa(fds[k].cin.sin_addr),ntohs(fds[k].cin.sin_port),m3.name);
                    close(k);
                    FD_CLR(k,&temps);
                    for(int l=max;l>=sfd;l--)
                    {
                        if(FD_ISSET(l,&temps))
                        {
                            max=l;
                            break;
                        }
                    }
                    for(int i=4;i<=max;i++)
                    {
                    write(i,&m3,sizeof(m3));
                    }
                    continue;
                }
                else if(m3.flag==1 | m3.flag==2 | m3.flag==3)
                {
                    for(int i=4;i<=max;i++)
                    {
                    if(i!=k)
                    {
                    write(i,&m3,sizeof(m3));
                    }
                    }
                }

            }
            }
        }
    }
   return 0;
}

客户端:

#include <myhead.h>
int sfd;
typedef struct mess
{
    char flag;
    char name[20];
    char message[128];
} mess;
void *p(void *a) // 读服务器发来的消息
{

    mess m;
    int len = sizeof(m);
    while (1)
    {
        bzero(&m, len);
        int a = read(sfd, &m, len);
        if (a == 0)
        {
            printf("服务器已断开........\n");
            exit(0);
        }
        if (m.flag == 1) // 接收用户加入群聊的消息
        {
            printf("\033[4D系统消息:%s已加入群聊\n", m.name);
        }
        else if (m.flag == 2) // 接收系统消息
        {
            printf("\033[4D系统消息:%s\n", m.message);
        }
        else if (m.flag == 3) // 接收群聊中用户发送的消息
        {
            printf("\033[4D%s:%s\n", m.name, m.message);
        }
        else // 接收用户退出群聊的消息
        {
            printf("\033[4D%s退出群聊\n", m.name);
        }

        printf("你:");
        fflush(stdout);
    }
}
int main(int argc, char const *argv[])
{

    const char *IP = argv[1];
    int P = atoi(argv[2]);
    sfd = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP客户端
    if (sfd == -1)
    {
        perror("socket:");
        return -1;
    }
    struct sockaddr_in t; // 填充服务器端的iP和端口号,用于连接服务器端
    t.sin_addr.s_addr = inet_addr(IP);
    t.sin_family = AF_INET;
    t.sin_port = htons(P);
    char name2[20];
    printf("请输入姓名:");
    scanf("%s", name2);
    if (connect(sfd, (struct sockaddr *)&t, sizeof(t)) == -1) // 连接到服务器端
    {
        perror("connet:");
        return -1;
    }

    write(sfd, name2, strlen(name2));
    printf("登录成功\n");
    pthread_t id;
    if (pthread_create(&id, 0, p, NULL) != 0)
    {
        perror("create:");
        return -1;
    };
    mess m2;
    while (1)
    {

        bzero(&m2, sizeof(m2));
        m2.flag = 3;
        printf("你:");
        scanf("%s", m2.message);
        strcpy(m2.name, name2);
        if (strcmp(m2.message, "quit") == 0)
        {
            m2.flag = 4;
            write(sfd, &m2, sizeof(m2));
            printf("退出成功!\n");
            exit(0);
        }
        write(sfd, &m2, sizeof(m2));
    }
    close(sfd);
    return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值