真的寫的很不錯呦~html
思路參考博客:http://www.javashuo.com/article/p-xiygeust-bz.htmllinux
代碼參考博客:https://www.cnblogs.com/xudong-bupt/p/3483059.html編程
服務端代碼:服務器
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #define MYPORT 8887 #define QUEUE 20 #define BUFFER_SIZE 1024 int main() { // 實例化socket對象, 定義sockfd /* AF_INET 默認爲IPv4 * SOCK_STREAM 流式socket, for TCP * 0 協議, 默認選擇合適的協議 * */ int server_sockfd = socket(AF_INET, SOCK_STREAM, 0); ///定義sockaddr_in struct sockaddr_in server_sockaddr; server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_port = htons(MYPORT); server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 將套接字綁定到地址 // bind,成功返回0,出錯返回-1 if (bind(server_sockfd, (struct sockaddr *) &server_sockaddr, sizeof(server_sockaddr)) == -1) { perror("bind"); exit(1); } // 監聽 // listen,成功返回0,出錯返回-1 if (listen(server_sockfd, QUEUE) == -1) { perror("listen"); exit(1); } // 客戶端套接字 char buffer[BUFFER_SIZE]; struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); // 進入阻塞狀態,等待客戶鏈接 // 成功返回非負描述字,出錯返回-1 int conn = accept(server_sockfd, (struct sockaddr *) &client_addr, &length); if (conn < 0) { perror("connect"); exit(1); } // 循環 while (1) { memset(buffer, 0, sizeof(buffer)); // 接受消息 int len = recv(conn, buffer, sizeof(buffer), 0); printf("len: %d\n", len); //這裏是一直循環的,若是客戶端說一句話,而後結束之後,這裏一直循環,須要注意 if (strcmp(buffer, "exit\n") == 0) break; fputs(buffer, stdout); // 發送消息 send(conn, "hehe", 5, 0); } close(conn); close(server_sockfd); return 0; }
客戶端代碼:網絡
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #define MYPORT 8887 #define BUFFER_SIZE 1024 int main() { ///定義sockfd int sock_cli = socket(AF_INET,SOCK_STREAM, 0); ///定義sockaddr_in struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(MYPORT); ///服務器端口 servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服務器ip ///鏈接服務器,成功返回0,錯誤返回-1 if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("connect"); exit(1); } char sendbuf[BUFFER_SIZE]; char recvbuf[BUFFER_SIZE]; while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) { send(sock_cli, sendbuf, strlen(sendbuf),0); ///發送 if(strcmp(sendbuf,"exit\n")==0) break; recv(sock_cli, recvbuf, sizeof(recvbuf),0); ///接收 fputs(recvbuf, stdout); memset(sendbuf, 0, sizeof(sendbuf)); memset(recvbuf, 0, sizeof(recvbuf)); } close(sock_cli); return 0; }
服務端:數據結構
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> //數據類型定義 #include <sys/stat.h> //文件屬性 #include <netinet/in.h> //定義數據結構sockaddr_in #include <sys/socket.h> //提供socket函數和數據結構 #include <string.h> #include <unistd.h> #include <signal.h> #include <sys/ipc.h> #include <errno.h> #include <sys/shm.h> //共享內存 #include <time.h> #include<sys/time.h> #include <arpa/inet.h> #define PERM S_IRUSR | S_IWUSR //用戶讀寫 #define MYPORT 8080 //通訊端口 #define BACKLOG 10 //定義服務器段能夠鏈接的最大客戶數 #define MYHOST "192.168.2.137" #define WELCOME "|---------------Welcome to the chat room!----------------|"//當客戶端鏈接服務端時,向客戶端發送此字符串 //將int類型轉換成char*類型 void itoa(int i, char *string) { int mask = 1; while (i / mask >= 10) mask *= 10; while (mask > 0) { *string++ = i / mask + '0'; i %= mask; mask /= 10; } *string = '\0'; } //獲得當前系統的時間 void get_cur_time(char *time_str) { struct timeval now; gettimeofday(&now, NULL); strcpy(time_str, ctime(&now.tv_sec)); } //建立共享存儲區 int shm_create() { int shmid; //shmid = shmget(IPC_PRIVATE, 1024, PERM); if ((shmid = shmget(IPC_PRIVATE, 1024, PERM)) == -1) { fprintf(stderr, "Create Share Memory Error:%s\n\a", strerror(errno)); exit(1); } return shmid; } //端口綁定函數。建立套接字,並綁定到指定端口 int bindPort(unsigned short int port) { int sockfd; struct sockaddr_in my_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); //建立基於流套接字 //bzero(&(my_addr.sin_zero),0); bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = AF_INET; //IPV4協議族 my_addr.sin_port = htons(port); //轉換端口爲網絡字節序 my_addr.sin_addr.s_addr = inet_addr(MYHOST); if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) { perror("fail to bind"); exit(1); } printf("bind success!\n"); return sockfd; } int main(int argc, char *argv[]) { int sockfd, clientfd; //監聽套接字、客戶套接字 int sin_size, recvbytes; pid_t pid, ppid; //定義父子進程標記 char *buf, *read_addr, *write_addr, *temp, *time_str; //須要用到的緩衝區 struct sockaddr_in their_addr; //定義地址結構 int shmid; shmid = shm_create(); //建立共享存儲區 temp = (char *) malloc(255); time_str = (char *) malloc(50); sockfd = bindPort(MYPORT); //綁定端口 get_cur_time(time_str); printf("Time is : %s\n", time_str); if (listen(sockfd, BACKLOG) == -1) { //在指定端口上監聽 perror("fail to listen"); exit(1); } printf("listen....\n"); while (1) { /* if (listen(sockfd, BACKLOG) == -1) { perror("fail to listen"); exit(1); } */ //接受一個客戶端的鏈接請求 if ((clientfd = accept(sockfd, (struct sockaddr *) &their_addr, &sin_size)) == -1) { perror("fail to accept"); exit(1); } //獲得客戶端的IP地址輸出 char address[20]; inet_ntop(AF_INET, &their_addr.sin_addr, address, sizeof(address)); printf("accept from %s\n", address); send(clientfd, WELCOME, strlen(WELCOME), 0); //發送問候信息 buf = (char *) malloc(255); ppid = fork(); //建立子進程 if (ppid == 0) //子進程 { pid = fork(); //子進程建立子進程 while (1) { if (pid > 0) { //buf = (char *)malloc(255); //父進程用於接收信息 memset(buf, 0, 255); printf("OK\n"); if ((recvbytes = recv(clientfd, buf, 255, 0)) <= 0) { perror("fail to recv"); close(clientfd); raise(SIGKILL); exit(1); } write_addr = shmat(shmid, 0, 0); //shmat將shmid所表明的全局的共享存儲區關聯到本進程的進程空間 memset(write_addr, '\0', 1024); //把接收到的消息存入共享存儲區中 strncpy(write_addr, buf, 1024); //把接收到的消息鏈接此刻的時間字符串輸出到標準輸出 get_cur_time(time_str); strcat(buf, time_str); printf(" %s\n", buf); } else if (pid == 0) { //子進程用於發送消息 sleep(1); //子進程先等待父進程把接收到的信息存入共享存儲區 read_addr = shmat(shmid, 0, 0); //讀取共享存儲區的內容 //temp存儲上次讀取過的內容,每次先判斷是否已經讀取過該消息 if (strcmp(temp, read_addr) != 0) { strcpy(temp, read_addr); //更新temp,表示已經讀取過該消息 get_cur_time(time_str); strcat(read_addr, time_str); if (send(clientfd, read_addr, strlen(read_addr), 0) == -1) { perror("fail to send"); exit(1); } memset(read_addr, '\0', 1024); strcpy(read_addr, temp); } } else perror("fai to fork"); } } } printf("------------------------------------\n"); free(buf); close(sockfd); close(clientfd); return 0; }
客戶端2、客戶端三...架構
#include <stdio.h> #include <netinet/in.h> //定義數據結構sockaddr_in #include <sys/socket.h> //定義socket函數以及數據結構 #include <sys/types.h> #include <string.h> #include <stdlib.h> #include <netdb.h> #include <unistd.h> #include <signal.h> #include <time.h> #include <netinet/in.h> #include <arpa/inet.h> #define MYPORT 8080 #define MYHOST "192.168.2.137" int main(int argc, char *argv[]) { struct sockaddr_in clientaddr; //定義地址結構 pid_t pid; int clientfd, sendbytes, recvbytes; struct hostent *host; //主機信息數據結構 char *buf, *buf_read; // if (argc < 4) // { // printf("wrong usage"); // printf("%s host port name\n", argv[0]); // exit(1); // } // host = gethostbyname(argv[1]); if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("fail to create socket"); exit(1); } bzero(&clientaddr, sizeof(clientaddr)); clientaddr.sin_family = AF_INET; clientaddr.sin_port = htons(MYPORT); clientaddr.sin_addr.s_addr = inet_addr(MYHOST); //客戶端鏈接服務端 if (connect(clientfd, (struct sockaddr *)&clientaddr, sizeof(struct sockaddr)) == -1) { perror("fail to connect"); exit(1); } buf = (char *)malloc(120); memset(buf, 0, 120); buf_read = (char *)malloc(100); if (recv(clientfd, buf, 100, 0) == -1) { perror("fail to recv"); exit(1); } printf("\n%s\n", buf); pid = fork(); while (1) { if (pid > 0) { //父進程發送消息 strcpy(buf, "afsasdf"); strcat(buf, ":"); memset(buf_read, 0, 100); fgets(buf_read, 100, stdin); strncat(buf, buf_read, strlen(buf_read) - 1); if ((sendbytes = send(clientfd, buf, strlen(buf), 0)) == -1) { perror("fail to send"); exit(1); } } else if (pid == 0) { //子進程接受消息 memset(buf, 0, 100); if (recv(clientfd, buf, 100, 0) <= 0) { perror("fail to recv"); close(clientfd); raise(SIGSTOP); exit(1); } printf("%s\n", buf); } else perror("fork error"); } close(clientfd); return 0; }