<网络编程培训之四> 编写一个UDP聊天室

系列博客参考:http://blog.csdn.net/zy416548283/article/category/1108400
代码以编号对应放在Github上:https://github.com/zy416548283/networkProgramming

题目

要求是一个国外大学的课程设计:https://www.cs.uoregon.edu/Classes/15F/cis432/ 这里的Assignment–Programming project #1 简单翻译一下题目的要求,具体要求可以参考原文中的要求

使用udp socket编写一个聊天室,要求具备以下功能
* 每个客户端可以加入多个聊天室(channel);
* 启动客户端的时候 默认加入Common这个聊天室;
* /join ChannelName 是加入聊天室,如果聊天室不存在,就创建这个聊天室;
* /leave ChannelName 是退出聊天室
* /switch ChannelName是切换聊天室
* /list 列出当前存在的聊天室
* /who Channel 列出指定聊天室有的成员
* 不加”/”表示用户在当前聊天室的聊天内容

题目解读

  • 会使用前面学过的基础Linux下的socket基础api;
  • 报文的格式,题目中已经定义好了;
  • 会用到select、多线程之类的高级特性;
  • 可以使用STL里的一些数据结构,开发速度更快

关于实现

课程设计中也给出了通信用的关键数据结构,如下所示:

#ifndef DUCKCHAT_H
#define DUCKCHAT_H

/* Path names to unix domain sockets should not be longer than this */
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 108
#endif

/* This tells gcc to "pack" the structure. Normally, gcc will * inserting padding into a structure if it feels it is convenient. * When the structure is packed, gcc gaurantees that all the bytes * will fall exactly where specified. */
#define packed __attribute__((packed))

/* Define the length limits */
#define REQ_MAX 4096
#define USERNAME_MAX 32
#define CHANNEL_MAX 32
#define SAY_MAX 64
#define HOST_MAX 256

/* Define some types for designating request and text codes */
typedef int request_t;
typedef int text_t;
typedef int s2s_t;

/* Define codes for request types. These are the messages sent to the server. */
#define REQ_LOGIN 0
#define REQ_LOGOUT 1
#define REQ_JOIN 2
#define REQ_LEAVE 3
#define REQ_SAY 4
#define REQ_LIST 5
#define REQ_WHO 6
#define REQ_KEEP_ALIVE 7 /* Only needed by graduate students */


/* Define codes for text types. These are the messages sent to the client. */
#define TXT_SAY 0
#define TXT_LIST 1
#define TXT_WHO 2
#define TXT_ERROR 3

/* #define S2S_JOIN 8 #define S2S_LEAVE 9 #define S2S_SAY 10 */
//_____________________________________________________________________
/* This structure is used for a generic request type, to the server. */
struct request {
        request_t req_type;
} packed;
/* Once we've looked at req_type, we then cast the pointer to one of * the types below to look deeper into the structure. Each of these * corresponds with one of the REQ_ codes above. */
struct request_login {
        request_t req_type; /* = REQ_LOGIN */
        char req_username[USERNAME_MAX];
} packed;

struct request_logout {
        request_t req_type; /* = REQ_LOGOUT */
} packed;

struct request_join {
        request_t req_type; /* = REQ_JOIN */
        char req_channel[CHANNEL_MAX]; 
} packed;

struct request_leave {
        request_t req_type; /* = REQ_LEAVE */
        char req_channel[CHANNEL_MAX]; 
} packed;

struct request_say {
        request_t req_type; /* = REQ_SAY */
        char req_channel[CHANNEL_MAX]; 
        char req_text[SAY_MAX];
} packed;

struct request_list {
        request_t req_type; /* = REQ_LIST */
} packed;

struct request_who {
        request_t req_type; /* = REQ_WHO */
        char req_channel[CHANNEL_MAX]; 
} packed;

struct request_keep_alive {
        request_t req_type; /* = REQ_KEEP_ALIVE */
} packed;

//_____________________________________________________________________
/* This structure is used for a generic text type, to the client. */
struct text {
        text_t txt_type;
} packed;

/* Once we've looked at txt_type, we then cast the pointer to one of * the types below to look deeper into the structure. Each of these * corresponds with one of the TXT_ codes above. */
struct text_say {
        text_t txt_type; /* = TXT_SAY */
        char txt_channel[CHANNEL_MAX];
        char txt_username[USERNAME_MAX];
        char txt_text[SAY_MAX];
} packed;
/* This is a substructure used by struct text_list. */
struct channel_info {
        char ch_channel[CHANNEL_MAX];
} packed;

struct text_list {
        text_t txt_type; /* = TXT_LIST */
        int txt_nchannels;
        struct channel_info txt_channels[0]; // May actually be more than 0
} packed;
/* This is a substructure used by text_who. */
struct user_info {
        char us_username[USERNAME_MAX];
};

struct text_who {
        text_t txt_type; /* = TXT_WHO */
        int txt_nusernames;
        char txt_channel[CHANNEL_MAX]; // The channel requested
        struct user_info txt_users[0]; // May actually be more than 0
} packed;

struct text_error {
        text_t txt_type; /* = TXT_ERROR */
        char txt_error[SAY_MAX]; // Error message
};

#endif

实现源代码放在Github中:https://github.com/zy416548283/networkProgramming/tree/master/4

关于运行与测试

  • 课程设计中给出了测试用的server和client,64位Linux下的可执行文件;自测完成后,可以用它给的文件来测试下自己写的server和client
  • 我的本地运行结果如下:
    <网络编程培训之四> 编写一个UDP聊天室_第1张图片

你可能感兴趣的:(socket,UDP,聊天室)