3.7作业

网络聊天室:

程序代码:

ser.c

#include <myhead.h>
//定义消息类型结构体
struct xiaoxi {
    char type;
    char name[20];
    char text[100];
};

int main(int argc, const char* argv[])
{
    // 创建套接字
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sfd  == -1) 
	{
        perror("socket error");
        return -1;
    }
    // 设置端口快速重用
    int reuse = 1;
    if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) 
	{
        perror("setsockopt error");
        return -1;
    }

    // 绑定
    // 定义地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(atoi(argv[2]));
    sin.sin_addr.s_addr = inet_addr(argv[1]);
    
    if (bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) == -1) 
	{
        perror("bind error\n");
        return -1;
    }

    // 设置监听
    if ((listen(sfd, 128)) == -1)
	{
        perror("listen error\n");
        return -1;
    }
    // 4接受请求
    // 存储客户端信息结构体
    struct sockaddr_in cin;
    cin.sin_family = AF_INET;
    cin.sin_port = htons(atoi(argv[2]));
    cin.sin_addr.s_addr = inet_addr(argv[1]);
    socklen_t socklen = sizeof(cin);
    struct sockaddr_in arr_cin[1024];

    // 定义
    struct pollfd fds[1024];
    for (int i = 0; i < 1024; i++) 
	{
        fds[i].fd = -1;
        fds[i].events = POLLIN;
    }
    //将0和sfd放入数组
    fds[0].fd = 0;
    fds[1].fd = sfd;

    struct xiaoxi rec;//消息类型结构体变量
    char buf[128] = "";//接受消息的容器
    int newfd = -1; //存储文件描述符
    while (1) 
	{
        int res = poll(fds, 1024, -1);
        if (res < 0)
		{
            perror("poll error");
            return -1;
        }
		else if (res == 0)
		{
            printf("time out\n");
            return -1;
        }
        if (fds[0].revents == POLLIN)  //终端标准输入描述符
		{
            bzero(buf, sizeof(buf));
            fgets(buf, sizeof(buf), stdin);
            buf[strlen(buf) - 1] = 0;
            for (int j = 4; j < 1024; j++)
			{
                send(fds[j].fd, buf, sizeof(buf), 0);
            }
        }
        if (fds[1].revents == POLLIN)//sfd
		{ 
            if ((newfd = accept(sfd, (struct sockaddr*)&cin, &socklen)) == -1) 
			{
                perror("accept error\n");
            }
            arr_cin[newfd] = cin; //将地址信息存入cin
            printf("------[%s:%d]连接成功------\n", inet_ntoa(arr_cin[newfd].sin_addr), htons(arr_cin[newfd].sin_port));
            fds[newfd].fd = newfd; //新生成的文件描述符放入数组
            fds[newfd].events = POLLIN;
        }
        for (int i = 4; i < 1024; i++) 
		{
            if (fds[i].fd < 0) 
			{
                continue;
            }
            if (fds[i].revents == POLLIN) 
			{
                bzero(buf, sizeof(buf));
                bzero(buf, sizeof(buf));
                int res = recv(fds[i].fd, &rec, sizeof(rec), 0); //接收客户端消息
                if (res == 0)
				{
                    close(fds[i].fd);
                    printf("------[%s:%d]断开连接------\n", inet_ntoa(arr_cin[fds[i].fd].sin_addr), htons(arr_cin[fds[i].fd].sin_port));
                    fds[i].fd = -1;
                    arr_cin[fds[i].fd].sin_addr.s_addr = 0;
                    arr_cin[fds[i].fd].sin_port = 0;
                    continue;
                }
                // 判断消息类型
                if (rec.type == 'L') // 登录消息
				{ 
                    for (int j = 4; j < 1024; j++)//发送给每个客户端
					{ 
                        if (j == i)
						{
                            continue;
                        }
                        bzero(buf, sizeof(buf));
                        sprintf(buf, "----------%s上线-----------", rec.name);
                        send(fds[j].fd, buf, strlen(buf), 0);
                    }
                } 
				else if (rec.type == 'C') // 聊天消息
				{ 
                    for (int j = 4; j < 1024; j++) 
					{
                        if (j == i) 
						{
                            continue;
                        }
                        bzero(buf, sizeof(buf));
                        sprintf(buf, "%s:%s", rec.name, rec.text);
                        send(fds[j].fd, buf, strlen(buf), 0);
                    }
                } 
				else 
				{                        //退出消息
                    //(rec.type == 'Q')
                    for (int j = 4; j < 1024; j++) 
					{
                        if (j == i)
						{
                            continue;
                        }
                        bzero(buf, sizeof(buf));
                        sprintf(buf, "-----------%s下线------------", rec.name);
                        send(fds[j].fd, buf, strlen(buf), 0);
                    }
                }
            }
        }
    }
    return 0;
}

cli.c

#include <myhead.h>

struct xiaoxi {
    char type;
    char name[20];
    char text[100];
};

int main(int argc, const char* argv[])
{
    // 创建套接字
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    if (cfd  == -1) 
	{
        perror("socket error\n");
        return -1;
    }

    // 端口快速重用
    int reus = 1;
    if ((reus = setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &reus, sizeof(reus))) == -1) 
	{
        perror("setsockopt error\n");
        return -1;
    }
	

    // 定义地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(atoi(argv[2]));
    sin.sin_addr.s_addr = inet_addr(argv[1]);
   
    // 向客户端发送连接请求
    if (connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) == -1)
	{
        perror("connect error");
        return -1;
    }


    struct xiaoxi sendi;

    char buf[100] = "";
    char nbuf[20] = "";

    
    struct pollfd fds[2];
    fds[0].fd=0;
    fds[0].events = POLLIN;

    fds[1].fd=cfd;
    fds[1].events = POLLIN;




    printf("请输入用户名:");
    fgets(nbuf,sizeof(nbuf),stdin);
    nbuf[strlen(nbuf)-1]=0;
    sendi.type = 'L';
    strcpy(sendi.name, nbuf);

    send(cfd, &sendi, sizeof(sendi), 0);
    while (1) 
	{
        int res = poll(fds,2,-1);           //阻塞检测
        if (fds[0].revents == POLLIN) 
        {
            bzero(buf, sizeof(buf));
            fgets(buf,sizeof(buf),stdin);
            buf[strlen(buf)-1]=0;
            sendi.type = 'C';    
            if(strcmp(buf,"quit")==0)
            {
                sendi.type = 'Q';
                sendto(cfd, &sendi, sizeof(sendi), 0, (struct sockaddr*)&sin, sizeof(sin));
                break;
            }
            strcpy(sendi.text,buf);
            sendto(cfd, &sendi, sizeof(sendi), 0, (struct sockaddr*)&sin, sizeof(sin));
        }
        if (fds[1].revents == POLLIN)
		{
            bzero(buf, sizeof(buf));
            int res = recv(cfd, buf, sizeof(buf), 0);
            printf("%s\n", buf);
            if (res == 0) 
			{
                printf("服务器下线\n");
                break;
            }
            
        }
    }
    close(cfd);
    return 0;
}

运行结果:

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值