4月14日

网络聊天室(还有推出未完成)

/服务器/

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<sys/stat.h>
#include<string.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<arpa/inet.h>
#include<pthread.h>
#include<sys/wait.h>
#include<stdlib.h>


#define ERR_MSG(msg) do{\
    perror(msg);\
    printf("line: __%d__\n", __LINE__);\
}while(0)


//服务器IP端口信息
#define IP_SER      "192.168.8.151"
#define PORT_SER     8080

int sfd;

//客户端信息链表
typedef struct node
{
    struct sockaddr_in cin;
    char name[20];
    int len;
    struct node* next;
}save_cin_info;


//创建存储客户端信息结构体
//方便线程使用创建全局变量
save_cin_info list_cin;

//消息包结构体协议
struct message
{
    char type;
    char name[20];
    char text[128];
};


//线程回调函数声明
void* callback_RCV(void* arg);
void* callback_SND(void* arg);


int do_loin(struct message msg_rcv, struct sockaddr_in cin);
int do_chat(struct message msg_rcv, struct sockaddr_in cin);


/* condition */
int main(int argc, const char *argv[])
{
    基本框架///
    sfd = socket(AF_INET, SOCK_DGRAM,  0);
    if (sfd < 0)
    {
        ERR_MSG("socket");
        return -1;
    }

    struct sockaddr_in sin;
    sin.sin_family                 = AF_INET;
    sin.sin_port                 = htons(PORT_SER);
    sin.sin_addr.s_addr         = inet_addr(IP_SER);

    if (bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
    {
        ERR_MSG("bind");
        return -1;
    }
    printf("bind success __%d__\n", __LINE__);
    基本框架///

    //初始化存储客户端信息结构体
    memset(&list_cin.cin, 0, sizeof(list_cin.cin));

    //线程创建
    pthread_t tid_rcv, tid_snd;
    if (pthread_create(&tid_rcv, NULL, callback_RCV, NULL) != 0)
    {
        fprintf(stderr, "pthread_create failed\n");
        return -1;
    }
    if (pthread_create(&tid_snd, NULL, callback_SND, NULL) != 0)
    {
        fprintf(stderr, "pthread_create failed\n");
        return -1;
    }
    
    pthread_join(tid_rcv, NULL);
    pthread_join(tid_snd, NULL);

    close(sfd);
    return 0;
}

void* callback_RCV(void* arg)
{
    //接受协议
    struct message msg_rcv;
    memset(&msg_rcv, 0, sizeof(struct message));

    //客户端信息
    struct sockaddr_in cin;
    socklen_t cin_len = sizeof(cin);

    while (1)
    {
        memset(&msg_rcv, 0, sizeof(msg_rcv));
        int res_rcv = 0;
        res_rcv = recvfrom(sfd, &msg_rcv, sizeof(struct message), 0, (struct sockaddr*)&cin, &cin_len);
        if (res_rcv < 0)
        {
            ERR_MSG("recvfrom");
            return NULL;
        }
        printf("type = %c name = %s text = %s\n", msg_rcv.type, msg_rcv.name, msg_rcv.text);
        
        switch(msg_rcv.type)
        {
            case 'L':
                do_loin(msg_rcv, cin);
                break;
            case 'C':
                do_chat(msg_rcv, cin);
                break;
            case 'Q':
                //do_quit(msg_rcv);
                break;
            default:
                continue;
                break;
        }
    }

}

int do_loin(struct message msg_rcv, struct sockaddr_in cin)
{
    

    //遍历客户端信息结构体发送登录信息
    save_cin_info* temp1 = &list_cin;
    while (temp1->next != NULL)
    {
        temp1 = temp1->next;
        //发送给用户登录消息
        int res = 0;
        char buf_loin[64] = "";
        sprintf(buf_loin, "[ %s ] 登录聊天室\n", msg_rcv.name);
        res = sendto(sfd, buf_loin, sizeof(buf_loin), 0, (struct sockaddr*)&temp1->cin, (socklen_t)sizeof(temp1->cin));
        if (res < 0)
        {
            ERR_MSG("sendto");
            return -1;
        }
        printf("发出登录消息\n");
    }

    //创建节点添加到链表
    
    //初始化
    save_cin_info* new = (save_cin_info*)malloc(sizeof(save_cin_info));
    if (NULL == new)
    {
        ERR_MSG("malloc");
        return -1;
    }

    //将新客户端信息添加到新结构体中
    new->cin = cin;
    strcpy(new->name, msg_rcv.name);            //将用户端ip信息和用户名绑定
    new->next = NULL;

    //插入(头插)
    save_cin_info *temp2 = list_cin.next;
    list_cin.next = new;
    new->next = temp2;
    list_cin.len++;

    
    //遍历链表输出,检查所有用户名
    temp2 = &list_cin;
    while (temp2->next != NULL)
    {
        temp2 = temp2->next;
        printf("name = %s\n", temp2->name);
    }
    

    return 0;
}

int do_chat(struct message msg_rcv, struct sockaddr_in cin)
{
    int res = 0;
    char buf_chat[256] = "";
    //sprintf(buf_chat, "[ %s ] : %s\n", msg_rcv.name, msg_rcv.text);


    //遍历链表通过cin找到对应客户端的用户名
    char name[20] = "";
    save_cin_info* temp = &list_cin;


    printf("len = %d\n", list_cin.len);
    for (int i=0; i<list_cin.len; i++)
    {
        temp = temp->next;
        //获取cin对应的用户名
        strcpy(name, temp->name);
        printf("temp->name = %s\n", temp->name);

        //要回复给所有客户端的内容
        sprintf(buf_chat, "[ %s ] : %s\n", name, msg_rcv.text);

        res = sendto(sfd, buf_chat, sizeof(buf_chat), 0, (struct sockaddr*)&temp->cin, (socklen_t)sizeof(temp->cin));
        if (res < 0)
        {
            ERR_MSG("sendto");
            return -1;
        }
    }
    return 0;
}

void* callback_SND(void* arg)
{
    char buf_chat[128] = "";
    char buf_system[128] = "";
    int res = 0;
    scanf("%s", buf_system);

    save_cin_info* temp = &list_cin;
    for (int i=0; i<list_cin.len; i++)
    {
        temp = temp->next;

        //要回复给所有客户端的内容
        sprintf(buf_chat, "[ system ] : %s\n", buf_system);
        res = sendto(sfd, buf_chat, sizeof(buf_chat), 0, (struct sockaddr*)&temp->cin, (socklen_t)sizeof(temp->cin));
        if (res < 0)
        {
            ERR_MSG("sendto");
            return NULL;
        }
    }
    return 0;

}


客户端

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<sys/stat.h>
#include<string.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<arpa/inet.h>
#include<pthread.h>
#include<sys/wait.h>
#include<stdlib.h>


#define ERR_MSG(msg) do{\
    perror(msg);\
    printf("line: __%d__\n", __LINE__);\
}while(0)

//服务器IP端口信息
#define IP_SER          "192.168.8.151"
#define PORT_SER          8080

//本地客户端IP端口信息
#define IP_CLI              "192.168.8.151"
#define PORT_CLI         8801

struct message
{
    char type;
    char name[20];
    char text[128];
};


//客户端套接字
int cfd;
//服务器IP和端口号信息

void* callback_text(void* arg);
void* callback_quit(void* arg);


int main(int argc, const char *argv[])
{
    //基本框架///
    cfd = socket(AF_INET, SOCK_DGRAM,  0);
    if (cfd < 0)
    {
        ERR_MSG("socket");
        return -1;
    }

    struct sockaddr_in sin;
    sin.sin_family                 = AF_INET;
    sin.sin_port                 = htons(PORT_SER);
    sin.sin_addr.s_addr         = inet_addr(IP_SER);
    
    //基本框架///


    //发送登录信息结构体
    struct message msg_loin;
    memset(&msg_loin, 0, sizeof(struct message));
    msg_loin.type = 'L';
    printf("请输入用户名>>> \n");
    scanf("%s", msg_loin.name);
    
    int s_res = 0;
    s_res = sendto(cfd, &msg_loin, sizeof(struct message), 0, (struct sockaddr*)&sin, sizeof(sin));
    if (s_res < 0)
    {
        ERR_MSG("sendto");
        return -1;
    }

    //char bb[32] = "";
    //recvfrom(cfd, bb, sizeof(bb), 0, NULL, NULL);
    
    //创建线程
    pthread_t tid_text, tid_quit;
    if (pthread_create(&tid_text, NULL, callback_text, &sin) != 0)
    {
        fprintf(stderr, "pthread_create failed\n");
        return -1;
    }
    if (pthread_create(&tid_quit, NULL, callback_quit, NULL) != 0)
    {
        fprintf(stderr, "pthread_create failed\n");
        return -1;
    }


    pthread_join(tid_text, NULL);
    pthread_join(tid_quit, NULL);

    close(cfd);
    return 0;
}


void* callback_text(void* arg)
{
    struct sockaddr_in sin = *(struct sockaddr_in*)arg;

    struct message msg_chat;
    memset(&msg_chat, 0, sizeof(msg_chat));
    msg_chat.type = 'C';

    printf("请输入发送的信息\n");


    char buf_chat[128] = "";
    int res = 0;
    while (strcmp(buf_chat, "quit"))
    {
        bzero(buf_chat, sizeof(buf_chat));
        scanf("%s", buf_chat);
        strcpy(msg_chat.text, buf_chat);
        res = sendto(cfd, &msg_chat, sizeof(struct message), 0, (struct sockaddr*)&sin, (socklen_t)sizeof(sin));
        if (res < 0)
        {
            ERR_MSG("sendto");
            return NULL;
        }

        //printf("buf_chat = %s size = %ld\n", buf_chat, strlen(buf_chat));
        
        


    }

}

void* callback_quit(void* arg)
{
    char buf_rcv[128] = "";
    while (1)
    {
        recvfrom(cfd, buf_rcv, sizeof(buf_rcv), 0, NULL, NULL);
        printf("%s\n", buf_rcv);
    }
}
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值