標籤:基於linux平台實現的流失通訊端用戶端 伺服器端代碼 用戶端代碼
(1)伺服器段代碼如下:
#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <netdb.h>#include <sys/types.h>#include <time.h>#include <sys/socket.h>#include <arpa/inet.h>#define BUFSIZE 512/* * 錯誤報表 */static void bail(const char *on_what){ fputs(strerror(errno), stderr); fputs(": ", stderr); fputs(on_what, stderr); fputc('\n', stderr); exit(1);}int main(int argc, char *argv[]){ int sockfd; /* 伺服器通訊端 */ int new_fd; /* 伺服器串連通訊端 */ struct sockaddr_in server_addr; /* 伺服器監聽通訊端 */ struct sockaddr_in client_addr; /* 用戶端IP地址 */ socklen_t size; int portnumber; char reqBuf[BUFSIZE]; /* 應用接收緩衝 */ char dtfmt[BUFSIZE]; /* 日期-時間結果字串 */ time_t td; /* 當前日期和時間 */ struct tm tm; /* 日期時間結構體 */ int z; if(argc != 2){ fprintf(stderr, "Usage: %s portnumber\a\n", argv[0]); exit(1); } if((portnumber = atoi(argv[1]))<0){ fprintf(stderr, "Usage: %s portnumber\a\n", argv[0]); exit(1); } /* 建立伺服器監聽通訊端 */ if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1){ fprintf(stderr, "Socket error: %s\a\n", strerror(errno)); exit(1); } /* 為監聽通訊端準備IP地址和連接埠 */ memset(&server_addr, 0, sizeof server_addr); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(portnumber); /* 綁定通訊端到指定地址和連接埠 */ if ((bind (sockfd, (struct sockaddr *)(&server_addr), sizeof server_addr)) == -1){ fprintf(stderr, "Bind error: %s\a\n", strerror(errno)); exit(1); } /* 監聽 */ if (listen(sockfd, 128) == -1) { fprintf(stderr, "Listen error: %s\n\a", strerror(errno)); exit(1); } printf("waiting for the client's request...\n"); /* 伺服器主迴圈處理 */ while (1) { size = sizeof (struct sockaddr_in); /* 接收一個用戶端串連並建立伺服器串連通訊端 */ if((new_fd = accept(sockfd, (struct sockaddr *)(&client_addr), &size)) == -1){ fprintf(stderr, "Accept error: %s\a\n", strerror(errno)); exit(1); } fprintf(stdout, "Server got connection from %s\n", inet_ntoa(client_addr.sin_addr)); for(;;) { /* 讀取用戶端發來的日期時間請求,若用戶端沒有發送請求, * 則伺服器將阻塞 */ z = read (new_fd, reqBuf, sizeof reqBuf); if(z < 0) bail("read()"); /* 伺服器檢查用戶端是否關閉了通訊端,此時read操作 * 返回0(EOF )。如果用戶端關閉了其通訊端,則伺服器 * 將執行close 結束此串連,然後開始接收下一個用戶端 * 的串連請求 */ if(z == 0) { close (new_fd); break; } /* * 向請求連接字串尾添加NULL字元構成完整的請求日 * 期時間字串 */ reqBuf[z] = 0; /* * 獲得伺服器當前日期和時間 */ time(&td); tm = *localtime(&td); /* * 根據請求日期文字的格式字串產生應答字串 */ strftime(dtfmt, /* 格式化結果 */ sizeof dtfmt, reqBuf, /* 用戶端請求格式字串 */ &tm);/* 將格式化結果發送給用戶端 */ z = write (new_fd, dtfmt, strlen(dtfmt)); if(z < 0) bail("write()"); } } }
(2)用戶端代碼:
#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <arpa/inet.h> #define BUFSIZE 512 static void bail(const char *on_what){ fputs(strerror(errno), stderr); fputs(": ", stderr); fputs(on_what, stderr); fputc('\n', stderr); exit(1); }int main (int argc, char *argv[]) { int sockfd; /*用戶端通訊端*/ char buf[BUFSIZE]; struct sockaddr_in server_addr; /* 伺服器IP地址*/ struct hostent *host; int portnumber; int nbytes; int z; char reqBuf[BUFSIZE]; /*用戶端請求格式字串 */ if (argc != 3) { fprintf(stderr, "Usage: %s hostname portnumber\a\n", argv[0]); exit(1); } if ((host = gethostbyname(argv[1])) == NULL) { fprintf(stderr, "Gethostname error\n"); exit(1); } if ((portnumber = atoi(argv[2])) < 0) { fprintf(stderr, "Usage: %s hostname portnumber\a\n", argv[0]); exit(1); } /*建立通訊端 */ if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { fprintf(stderr, "Socket Error: %s\a\n", strerror(errno)); exit(1); } /* 建立伺服器位址*/ memset(&server_addr, 0, sizeof server_addr); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(portnumber); server_addr.sin_addr = *((struct in_addr *)host->h_addr); /*連結的伺服器*/ if (connect(sockfd, (struct sockaddr *)(&server_addr), sizeof server_addr) == -1) { fprintf(stderr, "Connect Error: %s\a\n", strerror(errno)); exit(1); } printf("connected to server %s\n", inet_ntoa(server_addr.sin_addr)); /* *用戶端程式主迴圈,輸入‘quit’退出 */ for (;;) { /* 提示輸入日期時間格式字串 */ fputs("\nEnter format string(^D or 'quit' to exit): ", stdout); if (!fgets(reqBuf, sizeof reqBuf, stdin)) { printf("\n"); break; /* EOF */ } /* * 為日期時間請求字串添加NULL字串作為結尾,另外同時去掉末尾的分行符號 */ z = strlen(reqBuf); if (z > 0 && reqBuf[--z] == '\n') reqBuf[z] = 0; if (z == 0) /*用戶端進輸入了enter */ continue; /* * 輸入 quit 退出 */ if (!strcasecmp(reqBuf, "QUIT")) { printf("press any key to end client.\n"); getchar(); break; } /* * 發送日期時間請求字串到伺服器,注意請求資訊中去掉了NULL字元 */ z = write(sockfd, reqBuf, strlen(reqBuf)); printf("client has sent ??%s?? to the sever\n", reqBuf); if (z < 0) bail("write()"); /* * 從用戶端通訊端中讀取伺服器發回的應答 */ if ((nbytes = read(sockfd, buf, sizeof buf)) == -1) { fprintf(stderr, "Read Error: %s\n", strerror(errno)); exit(1); } /* * 若伺服器由於某一種原因關閉了連結,則客戶段需要處理此事件 */ if (nbytes == 0) { /* ????EOF */ printf("server has closed the socket.\n"); printf("press any key to exit...\n"); getchar(); break; } buf[nbytes] = '\0'; /* * 輸出日期時間結果 */ printf("result from %s port %u :\n\t'%s'\n", inet_ntoa(server_addr.sin_addr), (unsigned)ntohs(server_addr.sin_port), buf); } close(sockfd); return 0;}
(3)執行程式
基於Linux平台實現的流式通訊端用戶端伺服器端代碼