[关闭]
@zwh8800 2017-08-23T02:04:44.000000Z 字数 5106 阅读 190711

算是课后作业吧…

blog 归档 unix 网络编程 系统编程


功能:聊天室服务器,可用telnet直接连接到服务器,发送消息则在聊天室内的所有用户都能看见。使用select实现


功能:聊天室服务器

可用telnet直接连接到服务器,发送消息则在聊天室内的所有用户都能看见。

使用select实现

  1. #include <sys/select.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <arpa/inet.h>
  5. #include <unistd.h>
  6. #include <stddef.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include <errno.h>
  11. #define max(a, b) ((a) > (b) ? (a) : (b))
  12. struct filedescriptor_node
  13. {
  14. int fd;
  15. struct filedescriptor_node* next;
  16. };
  17. struct filedescriptor_set
  18. {
  19. size_t len;
  20. struct filedescriptor_node* head;
  21. struct filedescriptor_node* iter;
  22. int max_fd;
  23. fd_set fds;
  24. };
  25. int fds_init(struct filedescriptor_set* _this)
  26. {
  27. bzero(_this, sizeof(struct filedescriptor_set));
  28. FD_ZERO(&_this->fds);
  29. return 0;
  30. }
  31. struct filedescriptor_set*
  32. fds_create()
  33. {
  34. struct filedescriptor_set* _this;
  35. _this = malloc(sizeof(struct filedescriptor_set));
  36. if (_this == NULL)
  37. return NULL;
  38. if (fds_init(_this) == -1)
  39. {
  40. free(_this);
  41. return NULL;
  42. }
  43. return _this;
  44. }
  45. int fds_add(struct filedescriptor_set* _this, int fd)
  46. {
  47. struct filedescriptor_node* p;
  48. p = malloc(sizeof(struct filedescriptor_node));
  49. if (p == NULL)
  50. return -1;
  51. p->fd = fd;
  52. p->next = _this->head;
  53. _this->head = p; /* 在head前插入新节点 */
  54. ++_this->len;
  55. if (fd > _this->max_fd)
  56. _this->max_fd = fd;
  57. FD_SET(fd, &_this->fds);
  58. return 0;
  59. }
  60. int fds_remove(struct filedescriptor_set* _this, int fd)
  61. {
  62. struct filedescriptor_node* p;
  63. if (_this->head->fd == fd)
  64. {
  65. p = _this->head;
  66. _this->head = p->next;
  67. free(p);
  68. }
  69. else
  70. {
  71. for (p = _this->head; p->next != NULL; p = p->next)
  72. if (p->next->fd == fd)
  73. break; /* 令p指向fd的前一个 */
  74. if (p->next == NULL)
  75. return -1;
  76. }
  77. --_this->len;
  78. if (fd == _this->max_fd)
  79. {
  80. _this->max_fd = 0; /* _this->max_fd = _this->head->fd不正确,
  81. this->head可能为NULL */
  82. for (p = _this->head; p != NULL; p = p->next)
  83. if (p->fd > _this->max_fd)
  84. _this->max_fd = p->fd;
  85. }
  86. FD_CLR(fd, &_this->fds);
  87. return 0;
  88. }
  89. fd_set fds_getfdset(struct filedescriptor_set* _this)
  90. {
  91. return _this->fds;
  92. }
  93. int fds_getmaxfd(struct filedescriptor_set* _this)
  94. {
  95. return _this->max_fd;
  96. }
  97. void fds_iter_init(struct filedescriptor_set* _this)
  98. {
  99. _this->iter = _this->head;
  100. }
  101. int fds_iter_next(struct filedescriptor_set* _this)
  102. {
  103. if (_this->iter != NULL)
  104. {
  105. int fd = _this->iter->fd;
  106. _this->iter = _this->iter->next;
  107. return fd;
  108. }
  109. else
  110. return -1;
  111. }
  112. void fds_destroy(struct filedescriptor_set* _this)
  113. {
  114. struct filedescriptor_node *p, *q;
  115. p = _this->head;
  116. q = p->next;
  117. while (p != NULL)
  118. {
  119. free(p);
  120. p = q;
  121. if (q != NULL)
  122. q = q->next;
  123. }
  124. }
  125. void fds_delete(struct filedescriptor_set* _this)
  126. {
  127. fds_destroy(_this);
  128. free(_this);
  129. }
  130. int writen(int fd, char* buf, size_t len)
  131. {
  132. ssize_t n;
  133. size_t left = len;
  134. while (left > 0)
  135. {
  136. if ((n = write(fd, buf, len)) <= 0)
  137. {
  138. if (errno == EINTR)
  139. continue;
  140. else
  141. return -1;
  142. }
  143. left -= n;
  144. buf += n;
  145. }
  146. return len; /* 无论如何也要写完,否则就是错误 */
  147. }
  148. int readn(int fd, char* buf, size_t len)
  149. {
  150. ssize_t n;
  151. size_t left = len;
  152. while (left > 0)
  153. {
  154. if ((n = read(fd, buf, len)) < 0)
  155. {
  156. if (errno == EINTR)
  157. continue;
  158. else
  159. return -1;
  160. }
  161. else if (n == 0) /* 到达EOF */
  162. {
  163. break;
  164. }
  165. left -= n;
  166. buf += n;
  167. }
  168. return len - left; /* 可能提前到达EOF */
  169. }
  170. #define PORT 10086
  171. #define BUF_SIZE 4096
  172. typedef struct sockaddr SA;
  173. int main(int argc, char* argv[])
  174. {
  175. struct filedescriptor_set fds;
  176. int svrsock;
  177. struct sockaddr_in svraddr;
  178. svrsock = socket(AF_INET, SOCK_STREAM, 0);
  179. if (svrsock == -1)
  180. {
  181. perror("socket");
  182. exit(errno);
  183. }
  184. bzero(&svraddr, sizeof(svraddr));
  185. svraddr.sin_family = AF_INET;
  186. svraddr.sin_port = htons(PORT);
  187. svraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  188. if (bind(svrsock, (SA*)&svraddr, sizeof(svraddr)) == -1)
  189. {
  190. perror("bind");
  191. exit(errno);
  192. }
  193. if (listen(svrsock, 64) == -1)
  194. {
  195. perror("listen");
  196. exit(errno);
  197. }
  198. if (fds_init(&fds) == -1)
  199. {
  200. perror("fds_init");
  201. exit(errno);
  202. }
  203. while (1)
  204. {
  205. int fd;
  206. fd_set fdset;
  207. char buf[BUF_SIZE];
  208. size_t buflen;
  209. fdset = fds_getfdset(&fds);
  210. FD_SET(svrsock, &fdset);
  211. if (select(max(fds_getmaxfd(&fds), svrsock) + 1, &fdset, NULL, NULL, NULL) == -1)
  212. {
  213. perror("select");
  214. exit(errno);
  215. }
  216. if (FD_ISSET(svrsock, &fdset))
  217. {
  218. int cltsock;
  219. struct sockaddr_in cltaddr;
  220. socklen_t cltaddrlen = sizeof(cltaddr);
  221. char cltaddrstr[INET_ADDRSTRLEN];
  222. if ((cltsock = accept(svrsock, (SA*)&cltaddr, &cltaddrlen)) == -1)
  223. {
  224. perror("accept");
  225. exit(errno);
  226. }
  227. if (inet_ntop(AF_INET, &cltaddr.sin_addr, cltaddrstr, INET_ADDRSTRLEN) == NULL)
  228. {
  229. perror("inet_ntop");
  230. exit(errno);
  231. }
  232. /* 通知新用户到达 */
  233. printf("incoming connection from %s:%d\n", cltaddrstr, ntohs(cltaddr.sin_port));
  234. snprintf(buf, BUF_SIZE, "user %s:%d joined\n", cltaddrstr, ntohs(cltaddr.sin_port));
  235. buflen = strlen(buf);
  236. for (fds_iter_init(&fds); (fd = fds_iter_next(&fds)) >= 0;)
  237. {
  238. if (writen(fd, buf, buflen) == -1)
  239. {
  240. perror("writen");
  241. exit(errno);
  242. }
  243. }
  244. strncpy(buf, "Welcom\n", BUF_SIZE);
  245. buflen = strlen(buf);
  246. if (writen(cltsock, buf, buflen) == -1)
  247. {
  248. perror("writen");
  249. exit(errno);
  250. }
  251. if (fds_add(&fds, cltsock) == -1)
  252. {
  253. perror("fds_add");
  254. exit(errno);
  255. }
  256. }
  257. for (fds_iter_init(&fds); (fd = fds_iter_next(&fds)) >= 0;)
  258. {
  259. if (FD_ISSET(fd, &fdset))
  260. {
  261. int n;
  262. struct filedescriptor_node* old;
  263. if ((n = readn(fd, buf, BUF_SIZE)) == -1)
  264. {
  265. perror("readn");
  266. exit(errno);
  267. }
  268. else if (n == 0)
  269. {
  270. /*struct sockaddr_in cltaddr;
  271. socklen_t cltaddrlen = sizeof(cltaddr);
  272. char cltaddrstr[INET_ADDRSTRLEN];
  273. if (getpeername(fd, (SA*)&cltaddr, &cltaddrlen) == -1)
  274. {
  275. perror("getpeername");
  276. exit(errno);
  277. }
  278. if (inet_ntop(AF_INET, &cltaddr.sin_addr, cltaddrstr, INET_ADDRSTRLEN) == NULL)
  279. {
  280. perror("inet_ntop");
  281. exit(errno);
  282. }
  283. printf("%s disconnected the connection\n", cltaddrstr);
  284. snprintf(buf, BUF_SIZE, "user %s exited\n", cltaddrstr);
  285. buflen = strlen(buf);
  286. for (fds_iter_init(&fds); (fd = fds_iter_next(&fds)) >= 0;)
  287. {
  288. if (writen(fd, buf, buflen) == -1)
  289. {
  290. perror("writen");
  291. exit(errno);
  292. }
  293. }*/
  294. fds_remove(&fds, fd);
  295. continue;
  296. }
  297. old = fds.iter;
  298. for (fds_iter_init(&fds); (fd = fds_iter_next(&fds)) >= 0;)
  299. {
  300. if (writen(fd, buf, n) == -1)
  301. {
  302. perror("writen");
  303. exit(errno);
  304. }
  305. }
  306. fds.iter = old;
  307. }
  308. }
  309. }
  310. fds_destroy(&fds);
  311. return 0;
  312. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注