makefile:

  1. jchat: main.o login.o regist.o tcp.o
  2. gcc -w main.o login.o regist.o tcp.o -o jchat
  3. rm -f *.o *.gch *~
  4. main.o: main.c login.h regist.h tcp.h
  5. gcc -w -c main.c login.h regist.h tcp.h
  6. login.o: login.c login.h tcp.h
  7. gcc -w -c login.c login.h tcp.h
  8. regist.o: regist.c regist.h tcp.h
  9. gcc -w -c regist.c regist.h tcp.h
  10. tcp.o: tcp.c tcp.h
  11. gcc -w -c tcp.c tcp.h
  12.  
  13. clean:
  14. rm -f *.o *.gch *~ jchat

main.c:

  1. /*client/main.c*/
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7.  
  8. #include "login.h"
  9. #include "regist.h"
  10. #include "tcp.h"
  11.  
  12. #define MAXLINE 4096
  13. #define IP "127.0.0.1" // localhost
  14. #define PORT 12345
  15.  
  16. char sendbuff[MAXLINE], recvbuff[MAXLINE];//send buffer & recv buffer
  17. int sockfd;//socket file descriptor
  18.  
  19. int main(int argc, char *argv[])
  20. {
  21. ) {
  22. exit();
  23. }
  24.  
  25. ];
  26. ) {
  27. printf("login or regist:");
  28. scanf("%s", choice);
  29. ) {
  30. login(sockfd);
  31. }
  32. ) {
  33. regist(sockfd);
  34. }
  35. else {
  36. puts("input login or regist!");
  37. }
  38. }
  39. }

login.c:登入操作

  1. /*client/login.c*/
  2.  
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <sys/un.h>
  10.  
  11. #include "login.h"
  12. #include "tcp.h"
  13.  
  14. #define MAXLINE 4096
  15. #define IP "127.0.0.1" // localhost
  16. #define PORT 12345
  17.  
  18. ], passwd[];
  19. ];
  20.  
  21. /*
  22. * login to server
  23. * return 1 if succeed, 0 if fail
  24. */
  25. int login_succeed(int sockfd)
  26. {
  27. char sendbuff[MAXLINE], recvbuff[MAXLINE];
  28. sprintf(sendbuff, "l:%s:%s", user, passwd);
  29.  
  30. write(sockfd, sendbuff, strlen(sendbuff));
  31. //printf("sendbuff> '%s'\n", sendbuff);
  32. int n = read(sockfd, recvbuff, MAXLINE);
  33. recvbuff[n] = '\0';
  34. //printf("recvbuff> '%s'\n", recvbuff);
  35.  
  36. ) ;
  37. ;
  38. }
  39.  
  40. /*
  41. * send message to another user by server
  42. */
  43. void send_mesg(int sockfd)
  44. {
  45. char sendbuff[MAXLINE];
  46. int len = strlen(line);
  47. , j, k, pos;
  48.  
  49. while (i<len && (line[i]==' ' || line[i]=='\t')) ++i;
  50. j = i + ;
  51. while (j<len && line[j]!=' ' && line[j]!='\t') ++j;
  52. k = j + ;
  53. while (k<len && (line[k]==' ' || line[k]=='\t')) ++k;
  54.  
  55. , ulen = strlen(user);
  56. sendbuff[] = ] = ':';
  57. ; pos<ulen; ++pos) sendbuff[send_len++] = user[pos];
  58. sendbuff[send_len++] = ':';
  59. for (pos=i; pos<j; ++pos) sendbuff[send_len++] = line[pos];
  60. sendbuff[send_len++] = ':';
  61. for (pos=k; pos<len; ++pos) sendbuff[send_len++] = line[pos];
  62. sendbuff[send_len++] = '\0';
  63.  
  64. write(sockfd, sendbuff, strlen(sendbuff));
  65. //printf("send_mesg sendbuff> '%s'\n", sendbuff);
  66. }
  67.  
  68. /*
  69. * ask the server the online user
  70. */
  71. void check_online(int sockfd)
  72. {
  73. char sendbuff[MAXLINE], recvbuff[MAXLINE];
  74. sprintf(sendbuff, "o");
  75.  
  76. write(sockfd, sendbuff, strlen(sendbuff));
  77. //printf("check_online sendbuff> '%s'\n", sendbuff);
  78. int recv_len = read(sockfd, recvbuff, MAXLINE);
  79. recvbuff[recv_len] = '\0';
  80. //printf("check_online recvbuff> '%s'\n", recvbuff);
  81.  
  82. ) {
  83. printf("no one online\n");
  84. }
  85. else {
  86. , j, k, num = ;
  87. ][];
  88. while (i < recv_len) {
  89. j = i+;
  90. while (recvbuff[j] != ';') ++j;
  91. for (k=i; k<j; ++k) on[num][k-i] = recvbuff[k];
  92. on[num][j-i] = '\0';
  93. ++num;
  94. i = j + ;
  95. }
  96. printf("%d online user:\n", num);
  97. ; k<num; ++k) printf(" %s\n", on[k]);
  98. }
  99. }
  100.  
  101. /*
  102. * quit this client
  103. * quit the process fork by server
  104. */
  105. void quit(int sockfd)
  106. {
  107. char sendbuff[MAXLINE];
  108. sprintf(sendbuff, "q:%s", user);
  109.  
  110. write(sockfd, sendbuff, strlen(sendbuff));
  111. //printf("quit sendbuff> '%s'\n", sendbuff);
  112. }
  113.  
  114. /*
  115. * get unread message from server every 1 second
  116. */
  117. void get_mesg(int sockfd)
  118. {
  119. char sendbuff[MAXLINE], recvbuff[MAXLINE];
  120.  
  121. ) {
  122. sleep();
  123.  
  124. sprintf(sendbuff, "g:%s", user);
  125. write(sockfd, sendbuff, strlen(sendbuff));
  126.  
  127. //printf("get_mesg sendbuff> '%s'\n", sendbuff);
  128. int recv_len = read(sockfd, recvbuff, MAXLINE);
  129. recvbuff[recv_len] = '\0';
  130. //printf("get_mesg recvbuff> '%s'\n", recvbuff);
  131.  
  132. ) { // no message get
  133. continue;
  134. }
  135.  
  136. int num, i, j, k, l;
  137. num = i = ;
  138. ][];
  139. while (i < recv_len) {
  140. j = i + ;
  141. while (recvbuff[j] != ';') ++j;
  142.  
  143. k = i;
  144. while (k<j && recvbuff[k]!=':') ++k;
  145. ;
  146. for (l=i; l<k; ++l) line[line_len++] = recvbuff[l];
  147. line[line_len++] = ':';line[line_len++] = ' ';
  148. ; l<j; ++l) line[line_len++] = recvbuff[l];
  149. line[line_len] = '\0';
  150. puts(line);
  151.  
  152. i = j + ;
  153. }
  154. }
  155. }
  156.  
  157. /*
  158. * send online notice to server every 5 seconds
  159. */
  160. void online_notice(int sockfd)
  161. {
  162. char sendbuff[MAXLINE];
  163.  
  164. ) {
  165. sprintf(sendbuff, "a:%s", user);
  166.  
  167. write(sockfd, sendbuff, strlen(sendbuff));
  168. //printf("sendbuff> '%s'\n", sendbuff);
  169.  
  170. sleep();
  171. }
  172. }
  173.  
  174. /*
  175. * everything after login
  176. * thread 1 : receive user command
  177. * thread 2 : get unread message from server
  178. * thread 3 : send online notice to server
  179. */
  180. void login(int sockfd)
  181. {
  182. printf("user: ");
  183. scanf("%s", user);
  184. printf("password: ");
  185. scanf("%s", passwd);
  186.  
  187. if (login_succeed(sockfd)) {
  188. printf("welcome %s~\n", user);
  189. pid_t pid1 = fork();
  190. ) {
  191. pid_t pid2 = fork();
  192. ) { // thread 1 : input command
  193. while (gets(line)) {
  194. ]) {
  195. case 's': // send message
  196. send_mesg(sockfd);
  197. break;
  198. case 'o': // check online
  199. check_online(sockfd);
  200. break;
  201. case 'q': // quit
  202. quit(sockfd);
  203. kill(pid1, );
  204. kill(pid2, );
  205. printf("goobye %s ~\n", user);
  206. exit();
  207. break;
  208. }
  209. }
  210. }
  211. else { // thread 2 : get message from server
  212. get_mesg(sockfd);
  213. }
  214. }
  215. else { // thread 3 : send online notice
  216. online_notice(sockfd);
  217. }
  218. }
  219. else {
  220. printf("login failed\n");
  221. }
  222. }

login.h:

  1. /*client/login.h*/
  2.  
  3. #ifndef LOGIN_H
  4. #define LOGIN_H
  5.  
  6. void login(int sockfd);
  7.  
  8. #endif // LOGIN_H

regist.c:註冊操作

  1. /*client/regist.c*/
  2.  
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <sys/un.h>
  10.  
  11. #include "regist.h"
  12. #include "tcp.h"
  13.  
  14. #define MAXLINE 4096
  15.  
  16. extern char sendbuff[MAXLINE], recvbuff[MAXLINE];
  17. ], passwd[];
  18.  
  19. /*
  20. * regist new user
  21. * return 1 if succeed, 0 if fail
  22. */
  23. int regist_succeed(int sockfd)
  24. {
  25. sprintf(sendbuff, "r:%s:%s", user, passwd);
  26.  
  27. write(sockfd, sendbuff, strlen(sendbuff));
  28. int n = read(sockfd, recvbuff, MAXLINE);
  29. recvbuff[n] = ;
  30.  
  31. ) ;
  32. ;
  33. }
  34.  
  35. /*
  36. * regist
  37. */
  38. void regist(int sockfd)
  39. {
  40. printf("user: ");
  41. scanf("%s", user);
  42. printf("password: ");
  43. scanf("%s", passwd);
  44.  
  45. if (regist_succeed(sockfd)) {
  46. printf("regist a new user!\n");
  47. }
  48. else {
  49. printf("fail in regist new user!\n");
  50. }
  51. }

regist.h:

  1. /*client/regist.h*/
  2.  
  3. #ifndef REGIST_H
  4. #define REGIST_H
  5.  
  6. void regist(int sockfd);
  7.  
  8. #endif // REGIST_H

tcp.c:建立與伺服器的連線

  1. /*client/tcp.c*/
  2.  
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <sys/un.h>
  10. #include <netinet/in.h>
  11.  
  12. #include "tcp.h"
  13.  
  14. /*
  15. * link to assign IP and port
  16. * return the socket file descriptor
  17. */
  18. int link_server(char *IP, int port)
  19. {
  20. int sockfd;
  21. struct sockaddr_in servaddr;
  22.  
  23. )) < ) {
  24. fprintf(stderr, "socket error\n");
  25. ;
  26. }
  27.  
  28. memset(&servaddr, , sizeof(servaddr));
  29. servaddr.sin_family = AF_INET;
  30. servaddr.sin_port = htons(port);
  31. ) {
  32. fprintf(stderr, "inet_pton error for %s\n", IP);
  33. ;
  34. }
  35.  
  36. ) {
  37. fprintf(stderr, "connect error\n");
  38. ;
  39. }
  40.  
  41. return sockfd;
  42. }

tcp.h:

  1. /*client/tcp.h*/
  2.  
  3. #ifndef TCP_H
  4. #define TCP_H
  5.  
  6. /*
  7. * link IP:port using tcp
  8. * return sock file descriptor of the link (-1 if error)
  9. */
  10. int link_server(char *IP, int port);
  11.  
  12. #endif // TCP_H