linux下基于UDP的聊天室

    初学linux的socket编程,写几个简单的小实例。

程序在http://download.csdn.net/download/longmenwaideyu/8112301https://github.com/longmenwaideyu/linuxUDPChatroom都可以下载


chatServer.c

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <time.h>
#include <pthread.h>
#include "chatmsg.h"
#define SERVER_PORT 8888
#define MAX_MSG_SIZE 1024
struct sockaddr_in addrlist[1000];
int useridlist[1000];
time_t islive[10000];
void *checklive(void *args) {
    int i;
    while(1) {
        sleep(10);
        for (i = 0; i < 1000; i++) {
            if (useridlist[i] != -1) {
                if (time(NULL) - islive[useridlist[i]] >= 20) {
                useridlist[i] = -1;
                fprintf(stdout, "%d lost connect\n", useridlist[i]);
                }
            }
        }
    }
}
int adduser(struct sockaddr_in addr, int userid){
    int i;
    for (i = 0; i < 1000; i++) {
        if (useridlist[i] == -1) {
            addrlist[i] = addr;
            useridlist[i] = userid;
            islive[userid] = time(NULL);
            return 0;
        }
    }
    return -1;
}
void sendtouser(int sockfd, struct chatmsg msg) {
    int i;
    socklen_t addrlen = sizeof(struct sockaddr_in);
    for (i = 0; i < 1000; i++) {
        if (useridlist[i] != -1 && useridlist[i] != msg.userid) {
            sendto(sockfd, (void*)&msg, sizeof(msg), 0, (struct sockaddr*) &addrlist[i], addrlen);
        }
    }
}
void processMsg(int sockfd, struct sockaddr_in addr, struct chatmsg msg) {
    if (msg.msgtype == CHATMSG_JOIN) {
        adduser(addr, msg.userid);
    } else if (msg.msgtype == CHATMSG_CHAT) {
        sendtouser(sockfd, msg);
    } else if (msg.msgtype == CHATMSG_HEART) {
        islive[msg.userid] = time(NULL);
    }
}
void start_server(int sockfd) {
    struct sockaddr_in addr;
    int n;
    socklen_t addrlen;
    struct chatmsg msg;
    pthread_t th;
    pthread_create(&th, NULL, checklive, NULL);
    while (1) {
        addrlen = sizeof(struct sockaddr_in);
        n = recvfrom(sockfd, (void *)&msg, sizeof(struct chatmsg), 0, (struct sockaddr*)&addr, &addrlen);
        if (msg.msgtype == CHATMSG_CHAT)
            fprintf(stdout, "receved msg from %d: msgid: %d msg: %s", msg.userid, msg.msgid, msg.msgbuf);
        else if (msg.msgtype == CHATMSG_JOIN)
            fprintf(stdout, "%d join the room\n", msg.userid);
        processMsg(sockfd, addr, msg);
    }
}

int main () {
    int i;
    for (i = 0; i < 1000; i++) {
        useridlist[i] = -1;
    }
    for (i = 0; i < 10000; i++) {
        islive[i] = time(NULL);
    }
    int sockfd;
    struct sockaddr_in addr;
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        fprintf(stderr, "Socket Error: %s\n", strerror(errno));
        exit(1);
    }
    bzero(&addr, sizeof(struct sockaddr_in));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(SERVER_PORT);
    if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
        fprintf(stderr, "Bind Error: %s\n", strerror(errno));
        exit(1);
    }
    start_server(sockfd);
    close(sockfd);
    return 0;
}

chatClient.c

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "chatmsg.h"
#define SERVER_PORT 8888
#define MAX_MSG_SIZE 1024
int userid, msgid;
struct sockinfo {
    int sockfd;
    struct sockaddr_in* addr;
};
void *heartbeat(void* args) {
    int sockfd = ((struct sockinfo*)args)->sockfd;
    struct sockaddr_in* addr = ((struct sockinfo*)args)->addr;
    struct chatmsg msg;
    while (1) {
        sleep(10);
        msg.userid = userid;
        msg.msgtype = CHATMSG_HEART;
        msg.msgid = msgid++;
        sendto(sockfd, (void*)&msg, sizeof(struct chatmsg), 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in));
    }
}
void *recvchatmsg(void* args) {
    int sockfd = *(int*)args;
    struct chatmsg msg;
    while(1) {
        int n = recvfrom(sockfd, (void*)&msg, sizeof(struct chatmsg), 0, NULL, NULL);
        if (n < 0) {
            fprintf(stderr, "Recv error%s\n", strerror(errno));
        } else {
            fprintf(stdout, "%d:\t%s", msg.userid, msg.msgbuf);
        }
    }
}
void start_client(int sockfd, struct sockaddr_in *addr, socklen_t len) {
    pthread_t th1, th2;
    struct sockinfo args;
    args.sockfd = sockfd;
    args.addr = addr;
    pthread_create(&th1, NULL, recvchatmsg, (void*)&sockfd);
    pthread_create(&th2, NULL, heartbeat, (void*)&args);
    int n;
    char buffer[MAX_MSG_SIZE];
    struct chatmsg msg;
    msg.userid = userid;
    msg.msgid = msgid++;
    msg.msgtype = CHATMSG_JOIN;
    sendto(sockfd, (void*)&msg, sizeof(struct chatmsg), 0, (struct sockaddr*)addr, len);

    while (fgets(buffer, MAX_MSG_SIZE, stdin)) {
        msg.userid = userid;
        memcpy(msg.msgbuf, buffer, sizeof(buffer));
        msg.msgid = msgid++;
        msg.msgtype = CHATMSG_CHAT;
        sendto(sockfd, (void*)&msg, sizeof(struct chatmsg), 0, (struct sockaddr*)addr, len);
    }
}
int main (int argc, char **argv) {
    if (argc != 4) {
        fprintf(stderr, "usage ip port userid\n");
        exit(1);
    }
    msgid = 1;
    int sockfd, port;
    struct sockaddr_in addr;
    if ((userid = atoi(argv[3])) < 0) {
        fprintf(stderr, "usage ip port userid\n");
        exit(1);
    }
    if ((port = atoi(argv[2])) < 0) {
        fprintf(stderr, "usage ip port userid\n");
        exit(1);
    }
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        fprintf(stderr, "Socket Error: %s\n", strerror(errno));
        exit(1);
    }
    bzero(&addr, sizeof(struct sockaddr_in));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(SERVER_PORT);
    if (inet_aton(argv[1], &addr.sin_addr) < 0) {
        fprintf(stderr, "IP error\n");
        exit(1);
    }
    if (connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
        fprintf(stderr, "Connect Error: %s\n", strerror(errno));
        exit(1);
    }    
    start_client(sockfd, &addr, sizeof(struct sockaddr_in));
    close(sockfd);
    return 0;
}

chatmsg.h

#define CHATMSG_JOIN 0
#define CHATMSG_EXIT 1
#define CHATMSG_CHAT 2
#define CHATMSG_HEART 3
struct chatmsg
{
    int userid;
    int msgid;
    int msgtype;
    char msgbuf[1024];
};


留言: