makefile:
jchat: main.o login.o regist.o tcp.o gcc -w main.o login.o regist.o tcp.o -o jchat rm -f *.o *.gch *~ main.o: main.c login.h regist.h tcp.h gcc -w -c main.c login.h regist.h tcp.h login.o: login.c login.h tcp.h gcc -w -c login.c login.h tcp.h regist.o: regist.c regist.h tcp.h gcc -w -c regist.c regist.h tcp.h tcp.o: tcp.c tcp.h gcc -w -c tcp.c tcp.h clean: rm -f *.o *.gch *~ jchat
main.c:
/*client/main.c*/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include "login.h" #include "regist.h" #include "tcp.h" #define MAXLINE 4096 #define IP "127.0.0.1" // localhost #define PORT 12345 char sendbuff[MAXLINE], recvbuff[MAXLINE];//send buffer & recv buffer int sockfd;//socket file descriptor int main(int argc, char *argv[]) { if ((sockfd = link_server(IP, PORT)) == -1) { exit(1); } char choice[107]; while (1) { printf("login or regist:"); scanf("%s", choice); if (strcmp(choice, "login") == 0) { login(sockfd); } else if (strcmp(choice, "regist") == 0) { regist(sockfd); } else { puts("input login or regist!"); } } }
login.c:登录操作
/*client/login.c*/ #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include "login.h" #include "tcp.h" #define MAXLINE 4096 #define IP "127.0.0.1" // localhost #define PORT 12345 char user[107], passwd[107]; char line[107]; /* * login to server * return 1 if succeed, 0 if fail */ int login_succeed(int sockfd) { char sendbuff[MAXLINE], recvbuff[MAXLINE]; sprintf(sendbuff, "l:%s:%s", user, passwd); write(sockfd, sendbuff, strlen(sendbuff)); //printf("sendbuff> '%s'\n", sendbuff); int n = read(sockfd, recvbuff, MAXLINE); recvbuff[n] = '\0'; //printf("recvbuff> '%s'\n", recvbuff); if (strcmp(recvbuff, "y") == 0) return 1; else return 0; } /* * send message to another user by server */ void send_mesg(int sockfd) { char sendbuff[MAXLINE]; int len = strlen(line); int i = 1, j, k, pos; while (i<len && (line[i]==' ' || line[i]=='\t')) ++i; j = i + 1; while (j<len && line[j]!=' ' && line[j]!='\t') ++j; k = j + 1; while (k<len && (line[k]==' ' || line[k]=='\t')) ++k; int send_len = 2, ulen = strlen(user); sendbuff[0] = 's';sendbuff[1] = ':'; for (pos=0; pos<ulen; ++pos) sendbuff[send_len++] = user[pos]; sendbuff[send_len++] = ':'; for (pos=i; pos<j; ++pos) sendbuff[send_len++] = line[pos]; sendbuff[send_len++] = ':'; for (pos=k; pos<len; ++pos) sendbuff[send_len++] = line[pos]; sendbuff[send_len++] = '\0'; write(sockfd, sendbuff, strlen(sendbuff)); //printf("send_mesg sendbuff> '%s'\n", sendbuff); } /* * ask the server the online user */ void check_online(int sockfd) { char sendbuff[MAXLINE], recvbuff[MAXLINE]; sprintf(sendbuff, "o"); write(sockfd, sendbuff, strlen(sendbuff)); //printf("check_online sendbuff> '%s'\n", sendbuff); int recv_len = read(sockfd, recvbuff, MAXLINE); recvbuff[recv_len] = '\0'; //printf("check_online recvbuff> '%s'\n", recvbuff); if (recv_len <= 1) { printf("no one online\n"); } else { int i = 0, j, k, num = 0; char on[100][21]; while (i < recv_len) { j = i+1; while (recvbuff[j] != ';') ++j; for (k=i; k<j; ++k) on[num][k-i] = recvbuff[k]; on[num][j-i] = '\0'; ++num; i = j + 1; } printf("%d online user:\n", num); for (k=0; k<num; ++k) printf(" %s\n", on[k]); } } /* * quit this client * quit the process fork by server */ void quit(int sockfd) { char sendbuff[MAXLINE]; sprintf(sendbuff, "q:%s", user); write(sockfd, sendbuff, strlen(sendbuff)); //printf("quit sendbuff> '%s'\n", sendbuff); } /* * get unread message from server every 1 second */ void get_mesg(int sockfd) { char sendbuff[MAXLINE], recvbuff[MAXLINE]; while (1) { sleep(1); sprintf(sendbuff, "g:%s", user); write(sockfd, sendbuff, strlen(sendbuff)); //printf("get_mesg sendbuff> '%s'\n", sendbuff); int recv_len = read(sockfd, recvbuff, MAXLINE); recvbuff[recv_len] = '\0'; //printf("get_mesg recvbuff> '%s'\n", recvbuff); if (recv_len <= 1) { // no message get continue; } int num, i, j, k, l; num = i = 0; char on[100][21]; while (i < recv_len) { j = i + 1; while (recvbuff[j] != ';') ++j; k = i; while (k<j && recvbuff[k]!=':') ++k; int line_len = 0; for (l=i; l<k; ++l) line[line_len++] = recvbuff[l]; line[line_len++] = ':';line[line_len++] = ' '; for (l=k+1; l<j; ++l) line[line_len++] = recvbuff[l]; line[line_len] = '\0'; puts(line); i = j + 1; } } } /* * send online notice to server every 5 seconds */ void online_notice(int sockfd) { char sendbuff[MAXLINE]; while (1) { sprintf(sendbuff, "a:%s", user); write(sockfd, sendbuff, strlen(sendbuff)); //printf("sendbuff> '%s'\n", sendbuff); sleep(5); } } /* * everything after login * thread 1 : receive user command * thread 2 : get unread message from server * thread 3 : send online notice to server */ void login(int sockfd) { printf("user: "); scanf("%s", user); printf("password: "); scanf("%s", passwd); if (login_succeed(sockfd)) { printf("welcome %s~\n", user); pid_t pid1 = fork(); if (pid1 != 0) { pid_t pid2 = fork(); if (pid2 != 0) { // thread 1 : input command while (gets(line)) { switch (line[0]) { case 's': // send message send_mesg(sockfd); break; case 'o': // check online check_online(sockfd); break; case 'q': // quit quit(sockfd); kill(pid1, 9); kill(pid2, 9); printf("goobye %s ~\n", user); exit(0); break; } } } else { // thread 2 : get message from server get_mesg(sockfd); } } else { // thread 3 : send online notice online_notice(sockfd); } } else { printf("login failed\n"); } }
login.h:
/*client/login.h*/ #ifndef LOGIN_H #define LOGIN_H void login(int sockfd); #endif // LOGIN_H
regist.c:注册操作
/*client/regist.c*/ #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include "regist.h" #include "tcp.h" #define MAXLINE 4096 extern char sendbuff[MAXLINE], recvbuff[MAXLINE]; char user[107], passwd[107]; /* * regist new user * return 1 if succeed, 0 if fail */ int regist_succeed(int sockfd) { sprintf(sendbuff, "r:%s:%s", user, passwd); write(sockfd, sendbuff, strlen(sendbuff)); int n = read(sockfd, recvbuff, MAXLINE); recvbuff[n] = 0; if (strcmp(recvbuff, "y") == 0) return 1; else return 0; } /* * regist */ void regist(int sockfd) { printf("user: "); scanf("%s", user); printf("password: "); scanf("%s", passwd); if (regist_succeed(sockfd)) { printf("regist a new user!\n"); } else { printf("fail in regist new user!\n"); } }
regist.h:
/*client/regist.h*/ #ifndef REGIST_H #define REGIST_H void regist(int sockfd); #endif // REGIST_H
tcp.c:建立与服务器的连接
/*client/tcp.c*/ #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <netinet/in.h> #include "tcp.h" /* * link to assign IP and port * return the socket file descriptor */ int link_server(char *IP, int port) { int sockfd; struct sockaddr_in servaddr; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "socket error\n"); return -1; } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(port); if (inet_pton(AF_INET, IP, &servaddr.sin_addr) <= 0) { fprintf(stderr, "inet_pton error for %s\n", IP); return -1; } if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) { fprintf(stderr, "connect error\n"); return -1; } return sockfd; }
tcp.h:
/*client/tcp.h*/ #ifndef TCP_H #define TCP_H /* * link IP:port using tcp * return sock file descriptor of the link (-1 if error) */ int link_server(char *IP, int port); #endif // TCP_H