| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 564 人关注过本帖
标题:哪位大神进来帮忙看看linux下类似qq的程序实现功能
只看楼主 加入收藏
chengxi2006
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2014-10-19
结帖率:0
收藏
 问题点数:0 回复次数:0 
哪位大神进来帮忙看看linux下类似qq的程序实现功能
最近在网上找到一个类似qq的程序,我在虚拟机下的Ubuntu运行,只是知道用户登录和聊天的实现,但是对如何传送文件及其他功能还不是太了解,哪位大神帮忙看看,万分感谢~~~

代码如下:
// qqserver.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
 
#define CLIENT_LOGIN    100
#define CLIENT_CHAT     200
#define CLIENT_QUIT     300
 
#define SERVER_CHAT     400
#define SERVER_QUIT     500
 
#define CLIENT_ONLINE   600
 
struct node
{
    char name[20];
    struct sockaddr_in client_addr;
    struct node *next;
};
 
struct message
{
    long type;
    char name[20];//保存用户名
    char file_name[128];//保存发送文件的名字
    char dest[20];//保存目标用户名
    char mtext[512];//消息正文
};
 
struct node *create_list(void);
void insert_list(struct node *, char *, struct sockaddr_in *);
void delete_list(struct node *, char *);
 
void recv_message(int , struct node *);
void send_message(int , struct sockaddr *, pid_t);
void send_to_someone(int , struct node *, struct message *);
void send_to_all(int,  struct node *, struct message *);
 
void client_login(int , struct node *, struct message *, struct sockaddr_in *);
void client_online(int , struct node *, struct message *);
void client_chat(int , struct node *, struct message *);
void client_quit(int , struct node *, struct message *);
void server_chat(int , struct node *, struct message *);
void server_quit(int , struct node *, struct message *);
 
int main(int argc, const char *argv[])
{
    int socket_fd;
    pid_t pid;
    struct sockaddr_in server_addr;
    struct node *head;
 
    if (argc < 3)
    {
        fprintf(stderr, "usages : %s ip port\n", argv[0]);
        exit(-1);
    }
 
    if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("failed to create socket");
        exit(-1);
    }
 
    head = create_list();
 
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(atoi(argv[2]));
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);
 
    if (bind(socket_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("failed to bind");
        exit(-1);
    }
     
    if ((pid = fork()) < 0)
    {
        perror("failed to fork pid");
        exit(-1);
    }
 
    if (pid == 0)
        recv_message(socket_fd, head);
    else
        send_message(socket_fd, (struct sockaddr *)&server_addr, pid);
    return 0;
}
 
struct node *create_list(void)
{
    struct node *head;
 
    head = (struct node *)malloc(sizeof(struct node));
    head->next = NULL;
 
    return head;
}
 
void insert_list(struct node *head, char *name, struct sockaddr_in *client_addr)
{
    struct node *new;
 
    new = (struct node *)malloc(sizeof(struct node));
    strcpy(new->name, name);
    new->client_addr = *client_addr;
 
    new->next = head->next;
    head->next = new;
 
    return ;
}
 
void delete_list(struct node *head, char *name)
{
    struct node *p = head->next;
    struct node *q = head;
 
    while (p != NULL)
    {
        if (strcmp(p->name, name) == 0)
            break;
 
        p = p->next;
        q = q->next;
    }
 
    q->next = p->next;
    p->next = NULL;
    free(p);
 
    return ;
}
 
void recv_message(int socket_fd, struct node *head)//接受客户端发送过来的消息
{
    struct message msg;
    struct sockaddr_in client_addr;
    int client_addrlen = sizeof(struct sockaddr);
 
    while (1)
    {
        if (recvfrom(socket_fd, &msg, sizeof(msg), 0, (struct sockaddr *)&client_addr, &client_addrlen) < 0)
        {
            perror("failed to recvform client");
            exit(-1);
        }
 
        switch(msg.type)
        {
            case CLIENT_LOGIN:
                client_login(socket_fd, head, &msg, &client_addr);
                break;
                 
            case CLIENT_ONLINE:
                client_online(socket_fd, head, &msg);
                break;
                 
            case CLIENT_CHAT:
                client_chat(socket_fd, head, &msg);
                break;
 
            case CLIENT_QUIT:
                client_quit(socket_fd, head, &msg);
                break;
            
            case SERVER_CHAT:
                server_chat(socket_fd, head, &msg);
                break;
 
            case SERVER_QUIT:
                server_quit(socket_fd, head, &msg);
                break;
 
            default:
                break;
        }
    }
 
    return ;
}
 
void send_message(int socket_fd, struct sockaddr *server_addr, pid_t pid)//用于服务器向所有在线用户发送消息
{
    struct message msg;
    char buf[512];
 
    while(1)
    {
        memset(buf, 0, sizeof(buf));
        memset(&msg, 0, sizeof(msg));
 
        usleep(500);
 
        printf(">");//输入通信内容
        fflush(stdout);
        fgets(buf, sizeof(buf), stdin);
        buf[strlen(buf) - 1] = 0;
         
        strcpy(msg.mtext, buf);
        msg.type = SERVER_CHAT;
        if (strncmp(buf, "quit", 4) == 0)
        {
            msg.type = SERVER_QUIT;
            sendto(socket_fd, &msg, sizeof(msg), 0, server_addr, sizeof(struct sockaddr));
            kill(pid, SIGKILL);
            waitpid(pid, NULL, 0);
            exit(0);
        }
            sendto(socket_fd, &msg, sizeof(msg), 0, server_addr, sizeof(struct sockaddr));
    }
 
}
 
void client_login(int socket_fd, struct node *head, struct message *msg, struct sockaddr_in *client_addr)
{
    printf("********Login In********\n");
    printf("%s is Login In\n", msg->name);
    printf("************************\n");
 
    insert_list(head, msg->name, client_addr);
    send_to_all(socket_fd, head, msg);//向其他用户发送该用户的登录信息
    return ;
}
 
void client_online(int socket_fd, struct node *head, struct message *msg)//把在线人员信息发送给客户端
{
//  printf("=======Online Msg=======\n");
    struct node *p = head->next, *q = NULL;
    char buf[20];
    bzero(msg->mtext,20);
    while(p != NULL)
    {
        if(strcmp(p->name, msg->name) == 0)
        {
                q = p;
        }
        else
        {
            sprintf(buf,"%s ",p->name);
            strcat(msg->mtext, buf);
        }
        p = p->next;
    }
    sendto(socket_fd, msg, sizeof(struct message), 0, (struct sockaddr *)&(q->client_addr), sizeof(struct sockaddr));
     
//  printf("************************\n");
    return ;
}
 
void client_chat(int socket_fd, struct node *head, struct message *msg)
{
    printf("********Group Chat********\n");
    if(strlen(msg->file_name) == 0)//通过file_name成员是否为空判断是否要发送文件
    {
        printf("from:%s to:%s\n", msg->name,msg->dest);
        printf("msg: %s\n", msg->mtext);
    }
    else
    {
        printf("send file:%s\n",msg->file_name);
    }
    printf("**************************\n");
 
    if(strncmp("all", msg->dest, 3) != 0)//根据发送用户名确定是单个发送还是全体发送
        send_to_someone(socket_fd, head, msg);
    else
        send_to_all(socket_fd, head, msg);
 
    return ;
}
 
void client_quit(int socket_fd, struct node *head, struct message *msg)
{
    printf("*********Quit Msg********\n");
    printf("%s is Quit\n", msg->name);
    printf("*************************\n");
 
    delete_list(head, msg->name);
    send_to_all(socket_fd, head, msg);
 
    return ;
}
 
void server_quit(int socket_fd, struct node *head, struct message *msg)
{
    printf("server_quit()...\n");
    send_to_all(socket_fd, head, msg);
 
    return ;
}
 
void server_chat(int socket_fd, struct node *head, struct message *msg)
{
    printf("server_chat()...\n");
    printf("server msg:%s\n",msg->mtext);
    send_to_all(socket_fd, head, msg);
 
    return;
}
 
void send_to_someone(int socket_fd, struct node *head, struct message *msg)//向指定用户发送消息
{
    printf("send_to_someone()...\n");
    struct node *p = head->next;
 
    while(p != NULL)
    {
        if (strcmp(p->name, msg->dest) != 0)
        {
                p = p->next;
                continue;
        }
        sendto(socket_fd, msg, sizeof(struct message), 0, (struct sockaddr *)&p->client_addr, sizeof(struct sockaddr));        
        break;
    }
    printf("send_to_someone()...end!\n");
 
    return ;
}
 
void send_to_all(int socket_fd, struct node *head, struct message *msg)//向所有在线用户发送消息
{
    printf("send_to_all()...\n");
    struct node *p = head->next;
 
    while(p != NULL)
    {
        if (strcmp(p->name, msg->name) == 0)
        {
            p = p->next;
            continue;
        }
        sendto(socket_fd, msg, sizeof(struct message), 0, (struct sockaddr *)&p->client_addr, sizeof(struct sockaddr));
        printf("send to all:%s\n",msg->mtext);
        p = p->next;
    }
    printf("send_to_all()...end!\n");
 
    return ;
}



//qqclient.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
 
#define CLIENT_LOGIN    100
#define CLIENT_CHAT     200
#define CLIENT_QUIT     300
 
#define SERVER_CHAT     400
#define SERVER_QUIT     500
 
#define CLIENT_ONLINE   600
 
struct message
{
    long type;
    char name[20];//保存用户名
    char file_name[128];//保存发送文件的名字
    char dest[20];//保存目标用户名
    char mtext[512];//消息正文
};
 
void recv_message(int );
void send_message(int , struct sockaddr_in *, char *, pid_t);
 
void login_msg(struct message *);
void group_msg(int sockfd, struct message *msg);
void quit_msg(struct message *);
void server_msg(struct message *);
void server_quit(void);
void online_msg(struct message *msg);
void send_file(int socked_fd, struct message *msg, struct sockaddr *addr);
void recv_file(int sockfd, struct message *msg);
void send_string(int socked_fd, struct message *msg, struct sockaddr *addr);
 
int main(int argc, char *argv[])
{
    pid_t pid;
    int server_fd;
    struct sockaddr_in server_addr;
 
    if (argc < 4)
    {
        fprintf(stderr, "usages: %s ip port name\n", argv[0]);
        exit(-1);
    }
 
    if ((server_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("failed to create server_fd");
        exit(-1);
    }
 
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(atoi(argv[2]));
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);
 
    if ((pid = fork()) < 0)
    {
        perror("failed to fork pid");
        exit(-1);
    }
 
    if (pid == 0)
        recv_message(server_fd);
    else
        send_message(server_fd, &server_addr, argv[3], pid);
 
    return 0;
}
 
void recv_message(int server_fd)//接收服务器发送的消息
{
    struct message msg;
 
    while (1)
    {
        memset(&msg, 0, sizeof(msg));
 
        if (recvfrom(server_fd, &msg, sizeof(msg), 0, NULL, NULL) < 0)
        {
            perror("failed to recv server message");
            exit(-1);
        }
         
//      printf("msg.type=%ld\n",msg.type);
        switch(msg.type)
        {
            case CLIENT_LOGIN:
                login_msg(&msg);
                break;
 
            case CLIENT_CHAT:
                group_msg(server_fd, &msg);
                break;
 
            case CLIENT_QUIT:
                quit_msg(&msg);
                break;
                 
            case CLIENT_ONLINE:
                online_msg(&msg);
                break;
                 
            case SERVER_CHAT:
                server_msg(&msg);
                break;
 
            case SERVER_QUIT:
                server_quit();
                break;
 
            default:
                break;
        }
    }
 
    return ;
}
 
void send_message(int server_fd, struct sockaddr_in *server_addr, char *name, pid_t pid)//向服务器发送消息
{
    struct message msg;
    char buf[512];
 
    bzero(&msg, sizeof(msg));
    msg.type = CLIENT_LOGIN;//发送登录信息
    strcpy(msg.name, name);
 
    if (sendto(server_fd, &msg, sizeof(msg), 0,
                (struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0)
    {
        perror("failed to send login message");
        exit(-1);
    }
     
    msg.type = CLIENT_ONLINE;//发送查询在线信息
    strcpy(msg.name, name);
 
    if (sendto(server_fd, &msg, sizeof(msg), 0,
                (struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0)
    {
        perror("failed to send online message");
        exit(-1);
    }
     
    while(1)
    {
        memset(buf, 0, sizeof(buf));
        memset(&msg, 0, sizeof(msg));
 
        usleep(500);
         
        printf("to:");//输入要通信的对方用户名,若是"all",表示向所有用户发送
        fflush(stdout);
        fgets(buf, sizeof(buf), stdin);
        buf[strlen(buf) - 1] = 0;
        strcpy(msg.dest, buf);
         
        printf(">");//输入通信内容
        fflush(stdout);
        fgets(buf, sizeof(buf), stdin);
        buf[strlen(buf) - 1] = 0;
        if(strncmp(buf, "FILE", 4) == 0)//表示要传送文件
        {
            printf("Input file name:");
            fgets(msg.file_name, sizeof(msg.file_name), stdin);
            (msg.file_name)[strlen(msg.file_name)-1] = 0;
        }
 
        strcpy(msg.mtext, buf);
        strcpy(msg.name, name);
        msg.type = CLIENT_CHAT;
 
        if (strncmp(buf, "quit", 4) == 0)
        {
            msg.type = CLIENT_QUIT;
 
            if (sendto(server_fd, &msg, sizeof(msg), 0,
                        (struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0)
            {
                perror("failed to send quit message");
                exit(-1);
            }
 
            kill(pid, SIGKILL);
            waitpid(pid, NULL, 0);
            exit(0);
        }
 
        send_string(server_fd, &msg, (struct sockaddr *)server_addr);
        if(strncmp(msg.mtext, "FILE", 4) == 0)//如果通信内容显示要传送文件,则进行传送文件处理
            send_file(server_fd, &msg, (struct sockaddr *)server_addr);
    }
 
    return ;
}
 
void login_msg(struct message *msg)//显示登录信息
{
    printf("######## Login in ########\n");
    printf("%s is login in\n", msg->name);
    printf("######## Login in ########\n");
 
    return ;
}
 
void online_msg(struct message *msg)//显示在线用户信息
{
    printf("======== Online Msg =======\n");
    printf("%s is online\n",msg->mtext);
    printf("======== Online Msg =======\n");
}
 
void group_msg(int sockfd, struct message *msg)//显示聊天信息
{
    printf("******** Group Msg ********\n");
    printf("from: %s\n", msg->name);
    printf("msg: %s\n", msg->mtext);
    if(strncmp(msg->mtext, "FILE", 4) == 0)//如果发送过来的消息是要接收文件,则进行接收文件处理
    {
        printf("recv file:%s\n",msg->file_name);
        recv_file(sockfd, msg);
    }
    printf("******** Group Msg ********\n");
     
    printf("to:");
    fflush(stdout);
 
    return ;
}
 
void quit_msg(struct message *msg)
{
    printf("######## Quit Msg ########\n");
    printf("%s is Quit\n", msg->name);
    printf("######## Quit Msg ########\n");
 
    return ;
}
 
void server_msg(struct message *msg)//显示服务器发送的信息
{
    printf("******** Server Msg ********\n");
    printf("server msg: %s\n", msg->mtext);
    printf("******** Server Msg ********\n");
 
    return ;
}
 
void server_quit(void )
{
    kill(getppid(), SIGKILL);
    exit(0);
}
 
void recv_file(int sockfd, struct message *msg)//接收文件
{
    FILE *fp;
    strcat(msg->file_name, "_copy");//在原文件名后添加_copy作为新文件名
    printf("start creat new file:%s\n",msg->file_name);
    fp = fopen(msg->file_name, "w");
    if(fp == NULL)
    {
        perror("open file error");
        return;
    }
     
    int write_bytes = 0;
    int len;
    while(recvfrom(sockfd, msg, sizeof(struct message), 0, NULL, NULL) > 0)//接收消息,并把消息内的正文写入文件
    {
        if(strncmp(msg->mtext, "end", 3) == 0)
            break;
        len = strlen(msg->mtext);
        write_bytes = fwrite(msg->mtext, 1, len, fp);
        printf("write_bytes=%d\n",write_bytes);
    }
    printf("end recv_file()...\n");
    fclose(fp);
 
    return;
}
 
void send_string(int socket_fd, struct message *msg, struct sockaddr *addr)//发送普通消息
{
    printf("start send_string()...\n");
        if(sendto(socket_fd, msg, sizeof(struct message), 0, addr, sizeof(struct sockaddr)) < 0)
        {
            perror("failed to send string");
            return;
        }
    printf("end send_string()...\n");
}
 
void send_file(int socket_fd, struct message *msg, struct sockaddr *addr)//发送文件
{
    printf("start send_file()...\n");
    FILE *fp;
    char buf[512];
     
//    printf("filename:%s",msg->file_name);
    fp = fopen(msg->file_name, "r");
    if(fp == NULL)
    {
        perror("fopen error");
        return ;
    }
   
    int read_bytes = 0;
    while((read_bytes = fread(buf, 1, 512, fp)) > 0)//传送文件
    {
        printf("read_bytes=%d\n",read_bytes);
        strncpy(msg->mtext, buf, read_bytes);
        if(sendto(socket_fd, msg, sizeof(struct message), 0, addr, sizeof(struct sockaddr)) < 0)
        {
            perror("failed to send file");
            return;
        }
        bzero(msg->mtext, sizeof(msg->mtext));
    }
 
    strcpy(msg->mtext, "end");//发送文件结束标志
    if(sendto(socket_fd, msg, sizeof(struct message), 0, addr, sizeof(struct sockaddr)) < 0)
    {
        perror("failed to send 'end'");
        return;
    }
 
    fclose(fp);
    printf("end send_file()...\n");
    return;
}

有点长,辛苦了
搜索更多相关主题的帖子: 用户登录 include linux 虚拟机 
2015-01-09 22:02
快速回复:哪位大神进来帮忙看看linux下类似qq的程序实现功能
数据加载中...
 
   



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

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