标题:【探讨】模拟聊天室程序
只看楼主
草狼
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:2
帖 子:577
专家分:1040
注 册:2010-4-6
结帖率:94.44%
 问题点数:0 回复次数:4 
【探讨】模拟聊天室程序
服务端程序:
程序代码:
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<stdio.h>
#include<sys/select.h>
#include<iostream>
using namespace std;

#define MAXLEN 1000
int client[FD_SETSIZE];  //用来存放当前以链接的套接字
int maxi;                 //记录client数组以用的最大下标

int sendToAll(int sockfd, int maxi)
{
    char buff[MAXLEN];
    int n;
    if( (n = read(sockfd, buff, MAXLEN)) == 0)
        return 0;
    for(int i=0; i<= maxi; ++i ) {
        if( client[i] >=0 && client[i] != sockfd) {
            write(client[i], buff, n);
        }
    }

    return n;
}

int main() {
    //创建监听套接字
    int listenSockd;
    if( (listenSockd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
        fputs("socket error", stderr);
        return -1;
    }

    //绑定地址和接口
    struct sockaddr_in servaddr;
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8888);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    if(bind(listenSockd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) {
        fputs("bind error", stderr);
        return -1;
    }
   
    //开始接听
    listen(listenSockd, 10);
   
    //初始化client数组和maxi, client数组值为-1表示未用
    maxi = -1;
    for(int i=0; i< FD_SETSIZE; ++i)
        client[i] = -1;
    
    //设置select监听事件
    int maxfd = listenSockd+1;
    fd_set rset, allset; //allset为每次需要监听的事件,rset为监听到的事件
    FD_ZERO(&allset);
    FD_SET(listenSockd, &allset);

    while(1) {
        rset = allset;
        int nready;
        nready = select(maxfd, &rset, NULL, NULL, NULL);
        
        //判断是否有新的连接
        if(FD_ISSET(listenSockd, &rset)) {
            int connfd,i;
            connfd = accept(listenSockd, NULL, NULL);
            
            //找到最前面没有被使用的,然后把新的套接字存入其中,
            //同时更新allset和maxi
            for(i = 0; i < FD_SETSIZE; ++i) {
                if(client[i] < 0) {
                    client[i] = connfd;
                    FD_SET(connfd, &allset);
                    if( connfd >= maxfd )
                        maxfd = connfd + 1;
                    break;
                }
            }
            if( i > FD_SETSIZE) {
                fputs("too many clients", stderr);
                return -1;
            }

            if(i > maxi)
                maxi = i;

            if(--nready <= 0) continue; 
        }

        //判断是否有套接字已经准备好读
        for(int i=0; i<= maxi; ++i) {
            if(client[i] < 0 ) continue;

            if(FD_ISSET(client[i], &rset)) {
                if( sendToAll(client[i], maxi) == 0 ) {
                    client[i] = -1;
                    FD_CLR(client[i], &allset);
                    shutdown(client[i], SHUT_RDWR);
                }
                
                if(--nready <= 0 ) break;
            }
        }
    }

    return 0;
}



客户端程序:
程序代码:
#include<sys/socket.h>
#include<stdio.h>
#include<sys/select.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<assert.h>

#define MAXLEN 1000
int main(int argc, char *argv[])
{
    assert( argc >= 2 );
    int sockfd;
    if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        fputs("socket error", stderr);
        return -1;
    }
    
    struct sockaddr_in clientaddr;
    bzero(&clientaddr, sizeof(clientaddr));
    clientaddr.sin_family = AF_INET;
    clientaddr.sin_port = htons(8888);
    inet_pton(AF_INET, argv[1], &clientaddr.sin_addr);
    if( connect(sockfd, (struct sockaddr *)&clientaddr, sizeof(clientaddr)) < 0){
        fputs("connect error", stderr);
        return -1;
    }

   int  flag = 0;
   char recvBuff[MAXLEN], sendBuff[MAXLEN];
   fd_set rset;
   FD_ZERO(&rset);

   while( 1 ) {
          FD_SET(sockfd, &rset);
        if( !flag)
            FD_SET(fileno(stdin), &rset);
        select(sockfd+1, &rset, NULL, NULL, NULL);
        
        if(FD_ISSET(sockfd, &rset)) {
            int n;
            if((n = read(sockfd, recvBuff, MAXLEN)) == 0){
                if(flag) return 0;
                else {
                    fputs("read error", stderr);
                    return -1;
                }
            }
            recvBuff[n] = '\0';
            fputs(recvBuff, stdout);
        }

        if(FD_ISSET(fileno(stdin), &rset)){
            int n;
            if((n = read(fileno(stdin), sendBuff, MAXLEN)) == 0) {
                flag = 1;
                FD_CLR(fileno(stdin), &rset);
                shutdown(sockfd, SHUT_WR);
                continue;
            } 

            write(sockfd, sendBuff, n);
        }
    }
    return 0;
}
搜索更多相关主题的帖子: include 聊天室 记录 return 
2012-03-01 11:25
月夜神宏
Rank: 1
等 级:新手上路
帖 子:4
专家分:0
注 册:2012-3-9
得分:0 
   我想知道这是什么啊  可以告诉我吗
2012-03-10 00:18
zaixuexi
Rank: 12Rank: 12Rank: 12
来 自:上海
等 级:火箭侠
威 望:8
帖 子:858
专家分:3233
注 册:2010-12-1
得分:0 
不错哦,会用select模型

技术问题,请不要以短消息方式提问
2012-03-12 21:49
madfrogme
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:21
帖 子:1160
专家分:1106
注 册:2009-6-24
得分:0 
这两行不明白是什么意思
#include<iostream>
using namespace std;

还有下面的赋值不太明白

        rset = allset;

The quieter you become, the more you can hear
2012-08-20 16:50
拓非
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2012-8-1
得分:0 
#include<iostream>
using namespace std;

怎么把c++也给整过来了。。
2012-10-24 11:31



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-361938-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.127954 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved