您的位置:首页 > 理论基础 > 计算机网络

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

2015-11-10 15:14 579 查看
系列博客参考: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

我的本地运行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: