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

来源:互联网 发布:手机淘宝爱逛街不见了 编辑:程序博客网 时间:2024/06/16 01:13

系列博客参考: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
  • 我的本地运行结果如下:
    result
1 0
原创粉丝点击