| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 744 人关注过本帖
标题:linux下用C语言写的聊天程序
只看楼主 加入收藏
残阳夕梦
Rank: 1
等 级:新手上路
帖 子:10
专家分:0
注 册:2013-3-13
结帖率:80%
收藏
已结贴  问题点数:2 回复次数:6 
linux下用C语言写的聊天程序
要求:两个客户端可以进行聊天,服务器用来中转信息。
我的主要思路是:对于每个客户端连接,服务器端建立子进程对其进行处理,注册消息格式:register aa bb(aa是用户名,bb是密码),服务器根据第一个字符串对其进行处理;登陆:login aa bb,登陆成功后可以进行chat、logout等后续操作,当收到chat dd hello时,便找到dd的socket地址和文件描述符,将消息转发给他。
可这时我发现消息根本无法转发,每个客户端连接时的new_fd都相同,消息只能回发给aa,这里我应该怎么实现呢,我看了好多程序,都是用线程,我想用子进程实现,希望大家提供点思路。。下面是我服务器端的代码
程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <error.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/stat.h>
#include <fcntl.h>

#define MAXDATASIZE 256
#define PORT 3000
#define BACKLOG 5
#define TM_L 14

struct users
{
    char name[50];
    char password[50];
    char state[5];
    char IP[20];
    long port;
    int fd;
};

typedef struct users user;


//定义查询函数
int selectdb(user **cl,int f)
{
    
    int i = sizeof(user);
    long length = lseek(f,0,SEEK_END);
    if (length < i)
    {
        *cl == malloc(20);
        puts("empty");
        
        return -1;
    }
    if (*cl != NULL)
    {
        free(*cl);
    }
    *cl = malloc(length);
    lseek(f,0,SEEK_SET);
    if (read(f, *cl, length) != length)
    {
        perror("error");
        return -2;
    }
    
    return 0;
}

//打印文件内容
void printdb(user * cl,int f)
{
    int i = sizeof(user);
    long length = lseek(f,0,SEEK_END);
    int j;
    char btime[TM_L + 1] = {0};
    char name[10] = {0};
    
    for (j = 0; j<length/i; j++)
    {
        memcpy(name,(cl+j) -> name, 10);
        //memcpy(btime, (cl+j) -> btime,TM_L);
        
        printf ("%s,%s,%s,%s,%ld,%d\n",
            
            name,
            (cl+j) ->password,
            (cl+j) ->state,(cl+j)->IP,(cl+j)->port,(cl+j)->fd
            
            );

    }
}

//检测登陆是否成功
int check(user * cl,int f,char * name,char * password)
{
    int i = sizeof(user);
    long length = lseek(f,0,SEEK_END);
    int j;    
    
    for (j=0; j<length/i; j++)
    {
        if (strcmp((cl+j)->name,name) == 0 && strcmp((cl+j)->password,password) == 0)
            return j;
        
    }
    return -1;
}

//插入
int insertdb(user * cr,int f,user *cl)
{
    
    int i;
    i = sizeof(user);
    int length = lseek(f,0,SEEK_END);
    //cr->id = (cl + (length/i) - 1)->id + 1;
    
    
    lseek(f,0,SEEK_END);
    if (write(f,cr,i) != i)
    {
        perror("error");
        return -1;
    }
    
    return 0;
}

//修改文件
int changedb(user * cc, int f, user *cl)
{
    int i = sizeof(user);
    long length = lseek(f,0,SEEK_END);
    long j;
    for (j=0; j<= length/i; j++)
    {
        if (strcmp((cl+j) -> name, cc -> name) == 0)
            break;
    }

    printf ("nihao");
    memcpy(cl+j,cc,i);
    lseek(f,0,SEEK_SET);
    printf ("%s\n",cl->name);
    if (write(f,cl,length) != length)
    {
        perror("error");
        return -1;
    }
    return 0;
}

//根据人名找到他的socket地址
struct sockaddr_in addr(char * name, int f, user *cl)
{
    struct sockaddr_in toaddr;
    bzero(&toaddr,sizeof(toaddr));
    toaddr.sin_family = AF_INET;
    int i = sizeof(user);
    long length = lseek(f,0,SEEK_END);
    long j;
    for (j=0; j<= length/i; j++)
    {
        if (strcmp((cl+j) -> name, name) == 0)
            break;
    }
    toaddr.sin_port = (cl+j) -> port;
    printf ("%ld\n",(cl+j) -> port);
    if (inet_aton("127.0.0.1",&toaddr.sin_addr) == 0)
    {
        printf ("addr convert error\n");
        exit(1);
    }
    
    return toaddr;    
}

//根据人名找到他的文件描述符
int fd(char * name, int f, user *cl)
{
    int fd;
    int i = sizeof(user);
    long length = lseek(f,0,SEEK_END);
    long j;
    for (j=0; j<= length/i; j++)
    {
        if (strcmp((cl+j) -> name, name) == 0)
            break;
    }
    printf ("(cl+j)->fd: %d\n",(cl+j)->fd);
    fd = (cl+j)->fd;
    
    return fd;
    
}

//根据socket找人名
char * name(struct sockaddr_in fromaddr, int f, user *cl)
{
    
    char * name = (char *)calloc(10,sizeof(char));
    int i = sizeof(user);
    long length = lseek(f,0,SEEK_END);
    long j;
    for (j=0; j<= length/i; j++)
    {
        if ((cl+j) -> port == fromaddr.sin_port)
            break;
    }
    printf ("%s\n",(cl+j)->name);
    strcpy(name, (cl+j) -> name);
    
    
    return name;
    
}

int main()
{
    user cr[10];
    user *cl;
    user cc;
    cl = NULL;
    int sockfd, sin_size, new_fd,nbytes;
    int i=0,loca[10],j=0,k,flag=0;
    char buf[MAXDATASIZE];
    struct sockaddr_in srvaddr,clientaddr;
    char * p,*p1,*p2,*p3,*p4;
    char command[10],cmd[10];
    
    int client[10];
    user user[100];
    
    char bufp[200];
    int len;
    int f;
    int res;

    
    FILE * fp1,*fp2;
    
    char file[50];
    
    //创建套接字
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if (sockfd == -1)
    {
        printf ("create sockfd error!\n");
        exit(1);
    }
    
    //为套接字分配地址
    bzero(&srvaddr,sizeof(srvaddr));
    srvaddr.sin_family = AF_INET;
    srvaddr.sin_port = htons(PORT);
    if (inet_aton("127.0.0.1",&srvaddr.sin_addr) == 0)
    {
        printf ("IP address transfer error!\n");
        close(sockfd);
        exit(1);
    }
    
    //绑定服务器
    if (bind(sockfd,(struct sockaddr *)&srvaddr,sizeof(struct sockaddr)) == -1)
    {
        printf ("bind error!\n");
        close(sockfd);
        exit(1);
    }
    
    //监听端口
    if (listen(sockfd,BACKLOG) == -1)
    {
        printf ("listen error\n");
        close(sockfd);
        exit(1);
    }

    f = open("qq.txt",O_RDWR | O_CREAT,0664);
    if (f == -1)
    {
        perror("error");
        return 1;
    }
    
    for(;;)
    {
        //接收客户端连接
        sin_size = sizeof(struct sockaddr_in);
        new_fd = accept(sockfd,(struct sockaddr *)&clientaddr,&sin_size);
        printf ("new_fd:%d\n",new_fd);
        if (new_fd == -1)
        {
            printf ("accept error!\n");
            continue;
        }
        printf ("new_fd:%d\n",new_fd);
                    
        if (!fork())
        {
            
            close(sockfd);
            //接收客户端消息
            nbytes = read(new_fd,buf,sizeof(buf));
            buf[nbytes] = '\0';
            printf ("receive message from client: %s\n",buf);
            strcpy(bufp,buf);
                
            p = strtok(buf," ");
            strcpy(cmd,p);
            printf ("%s\n",cmd);
            printf ("%d\n",strcmp(cmd,"login"));
            
            /*提取命令字——用户注册*/
            if (strcmp(cmd,"register") == 0)
            {
                p1 = strtok(NULL," ");
                strcpy(cr[i].name,p1);
                
                p2 = strtok(NULL," ");
                strcpy(cr[i].password,p2);
                
                strcpy(cr[i].state,"out");
                
                
                insertdb(&cr[i], f, cl);
                res = selectdb(&cl,f);
                if (res == -2)
                {
                    return 1;
                }
                else if(res == 0)
                {
                    printdb(cl,f);
                }                
                bzero(buf,sizeof(buf));
                strcpy(buf,"you have register successfully!");
                write(new_fd,buf,sizeof(buf));
                printf ("send messge to qqclient:%s\n",buf);
            }                
            /*提取命令字——登陆及后续操作*/
            if (strcmp(cmd,"login") == 0)
            {        
                p1 = strtok(NULL," ");
                p2 = strtok(NULL," ");
                
                int m=0;
                
                res = selectdb(&cl,f);
                m = check(cl,f,p1,p2);
                
                if (m >= 0)
                {
                    
                    strcpy(cc.name,p1);
                    
                    strcpy(cc.password,p2);
                    strcpy(cc.state,"on");
                    strcpy(cc.IP,inet_ntoa(clientaddr.sin_addr));
                    cc.port = clientaddr.sin_port;
                    cc.fd = new_fd;
                    selectdb(&cl,f);
                    
                
                    changedb(&cc,f,cl);
                    
                    strcpy(buf,"you have login successfully!");
                    write(new_fd,buf,sizeof(buf));
                    printf ("send messge to qqclient:%s\n",buf);
                    bzero(buf,sizeof(buf));
                    res = selectdb(&cl,f);
                    if (res == -2)
                    {
                        return 1;
                    }
                    else if(res == 0)
                    {
                        printdb(cl,f);
                    }
                    
                }
                while(1)
                {
                    //接收客户端消息
                    nbytes = read(new_fd,buf,sizeof(buf));
                    buf[nbytes] = '\0';
                    printf ("receive message from client: %s\n",buf);
                    
                    p = strtok(buf," ");
                    strcpy(cmd,p);
                    

                    
                    if (strcmp(cmd, "chat") == 0)
                    {
    
                        struct sockaddr_in toaddr;
                        char fromname[10];
                        char ss[10];
                        printf ("%s\n",buf);
                        p1 = strtok(NULL," ");
                        p2 = strtok(NULL," ");
                        strcpy(ss,p1);
                        res = selectdb(&cl,f);
                        printf ("%d\n",clientaddr.sin_port);
                        printf ("%s\n",name(clientaddr, f, cl));
                        strcpy(fromname,name(clientaddr, f, cl));
                        
                        printf ("%s %s\n",p1,p2);
                        
                        toaddr = addr(p1,f,cl);
                        int fdd;
                        printf("p1:%s\n",p1);
                        fdd = fd(p1, f, cl);
                        printf ("to port:%d\n",toaddr.sin_port);
                        sprintf(buf,"%s%s%s%s%s",cmd," ",fromname," ",p2);
                        printf ("%s\n",buf);
                        //write(new_fd,buf,sizeof(buf));
                        
                        printf("p1:%s\n",p1);
                        
                        printf ("judge:%d\n",fdd);
                        printf ("to port:%d %d\n",toaddr.sin_port,clientaddr.sin_port);
                        
                        
                        sendto(fdd,buf,strlen(buf),0,(struct sockaddr *)(&toaddr),sizeof(clientaddr));
                        
                        printf ("send message:%s\n",buf);
                    }
                }
            }
            close(new_fd);
            exit(0);
        }        
        close(new_fd);
        n--;
        
    }
    
    close(sockfd);
    
    return 0;

}


搜索更多相关主题的帖子: register 用户名 logout 服务器 linux 
2013-12-01 12:50
zhaogay
Rank: 7Rank: 7Rank: 7
来 自:宫
等 级:黑侠
帖 子:151
专家分:586
注 册:2013-10-10
收藏
得分:2 
代码好长,,楼主可以用消息队列将消息转过去啊,也可以直接把和请求回话的客户端的连接套接字发给下一个客户端,让他自己接收。

好好学习,天天想上
2013-12-01 13:10
鱼儿海
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:77
专家分:194
注 册:2013-8-14
收藏
得分:0 
不懂,学习学习
2013-12-01 18:05
haiboself
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:193
专家分:196
注 册:2013-10-23
收藏
得分:0 
膜拜一下
2013-12-01 18:07
积木10086
Rank: 1
等 级:新手上路
帖 子:38
专家分:0
注 册:2013-11-22
收藏
得分:0 
看不懂,但是后边一定会看懂的
2013-12-02 19:09
残阳夕梦
Rank: 1
等 级:新手上路
帖 子:10
专家分:0
注 册:2013-3-13
收藏
得分:0 
真的是各种问题,,一点一点调试,现在我能区分不同的客户端了,却发现只能单向发送消息,另一个人发回来的收不到。。有写过这方面的大神吗,,看到的话给指点一下。。

[ 本帖最后由 残阳夕梦 于 2013-12-4 00:21 编辑 ]
2013-12-04 00:19
embed_xuel
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:58
帖 子:3845
专家分:11385
注 册:2011-9-13
收藏
得分:0 
回复 6楼 残阳夕梦
你的代码,你整个项目设计说明以及代码注释都很少,而且变量命名太随意,变量是用到的时候在代码里随便找个位置就声明,都增加了阅读代码的难度,读着都费劲,谁还会帮你定位问题

总有那身价贱的人给作业贴回复完整的代码
2013-12-04 07:05
快速回复:linux下用C语言写的聊天程序
数据加载中...
 
   



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

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