原文做者:aircrafthtml
原文連接:https://www.cnblogs.com/DOMLX/p/9614820.htmlc++
1,什麼是標準I/O?實際上是指C語言裏的文件操做函數,如:fopen,feof,fgetc,fputs等函數,他們和平臺無關。編程
2,網絡通訊中使用標準I/O的優勢:網絡
良好的移植性。良好移植性這個不需多解釋,不只是I/O函數,全部的標準函數都具備良好的移植性。由於,爲了支持全部的操做系統(編譯器),這些函數都是按照ANSI C標準定義的。socket
標準I/O函數能夠利用緩衝提升性能。在網絡通訊中,read,write傳輸數據只有一種套接字緩衝,但使用標準I/O傳輸會有額外的緩衝,即I/O緩衝和套接字緩衝兩個。使用I/O緩衝主要是爲了提升性能,須要傳輸的數據越多時越明顯。由於,一次發送更多的數據要比分屢次發送一樣的數據性能要高。發送一次數據就對應一個數據包,每每數據包的頭信息比較大,它與數據大小無關。函數
3,網絡通訊中使用標準I/O的缺點:post
4,轉換函數性能
//將文件描述符轉換爲標準I/O函數中使用的FILE結構體指針
FILE * fdopen(int fildes, const char *mode);
成功時返回轉換的FILE結構體指針,失敗返回NULL學習//將FILE結構體指針轉換爲文件描述符
int fileno(FILE *stream);
成功返回轉換後的文件描述符,失敗返回-1ui
註釋:套接字中使用標準I/O,其實主要是運用在須要傳輸大量數據的狀況,由於其須要編寫額外代碼,因此並不像想象中的那麼經常使用。
先給個fdopen函數的簡單示例:
#include <stdio.h> main() { FILE * fp = fdopen(0, "w+"); fprintf(fp, "%s\n", "hello!"); fclose(fp); }
fileno示例:
#include <stdio.h> main() { FILE *fp; int fd; fp = fopen("/etc/passwd", "r"); fd = fileno(fp); printf("fd = %d\n", fd); fclose(fp); }
5.fgets與fputs函數:
1.fgets()
功能:有文件中讀取一字符串
定義:char *fgets(char *s, int size, FILE *stream)
說明:
fgets()用來從參數stream所指的文件讀入字符並存到參數s所指向的內存空間,
直到讀到換行字符\n,讀到文件尾或是讀到size-1個字符爲止,最後會加入NULL做爲文件結束。
返回值:
成功 返回s的指針
失敗 返回NULL
2.fputs()
功能:將一指定的字符串寫入文件內
定義: char * fputs(const *char s, FILE *stream)
說明:
fputs()用來將s所指的字符串寫到參數stream所指向的文件中
返回值:
成功 返回寫入字符串的個數
失敗 返回EOF
示例代碼:
include <stdio.h> int main() { int str[100]; fputs(fgets(str, 100, strin), strout); return 0; }
6.feof介紹:
1.在stdio.h中的宏定義
#define _IOEOF 0x0010
#define feof(_stream) ((_stream)->_flag & _IOEOF)
2.feof的使用:
feof用檢測流上的文件結束符,其返回值有兩種狀況:若是遇到文件結束,函數值爲非零值,不然函數值爲0。
注:此處的文件結束標誌是EOF,EOF的16進制代碼爲0xFF(十進制爲-1),特用在文本文件中,由於在文本文件中數據是以ASCⅡ代碼值的形式存放,普通字符的ASCⅡ代碼的範圍是32到127(十進制),與EOF不衝突,所以能夠直接使用。可是在二進制文件中,數據有可能出現-1,所以不能用EOF來做爲二進制文件的結束標誌,能夠經過feof函數來判斷。
注意了這些標準I/O函數速度是比日常的函數快不少不少的,不過也不是每次都用到,具體看對什麼狀況了
二.基於標準I/O函數實現套接字服務端與客戶端通訊
LINUX下服務端:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *message); int main(int argc, const char * argv[]) { int serv_sock, clnt_sock; char message[BUF_SIZE]; int str_len, i; struct sockaddr_in serv_adr, clnt_adr; socklen_t clnt_adr_sz; FILE *readfp; FILE *writefp; if(argc != 2) { printf("Usage: %s <port> \n", argv[0]); exit(1); } serv_sock = socket(PF_INET, SOCK_STREAM, 0); if(serv_sock == -1) error_handling("socket() error"); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = htonl(INADDR_ANY); serv_adr.sin_port = htons(atoi(argv[1])); if(bind(serv_sock, (struct sockaddr *) &serv_adr, sizeof(serv_adr)) == -1) error_handling("bind() error"); if(listen(serv_sock, 5) == -1) error_handling("listen() error"); clnt_adr_sz = sizeof(clnt_adr); for (i = 0; i < 5; i++) { clnt_sock = accept(serv_sock, (struct sockaddr *) &clnt_adr, &clnt_adr_sz); if(clnt_sock == -1) error_handling("accept() error"); else printf("Connected client %d \n", i+1); //將文件描述符轉換爲FILE結構體指針 readfp = fdopen(clnt_sock, "r"); writefp = fdopen(clnt_sock, "w"); while (!feof(readfp)) { //轉化爲標準I/O操做 fgets(message, BUF_SIZE, readfp);//至關於read,接收 fputs(message, writefp); //至關於write,發送 fflush(writefp); //刷新緩衝,當即顯示而不是一直放緩衝中,保證當即將數據傳輸到客服端 } fclose(readfp); fclose(writefp); } close(serv_sock); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
LINUX下客戶端:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *message); int main(int argc, const char * argv[]) { int sock; char message[BUF_SIZE]; int str_len; struct sockaddr_in serv_adr; FILE *readfp; FILE *writefp; if(argc != 3) { printf("Usage: %s <IP> <port> \n", argv[0]); exit(1); } sock = socket(PF_INET, SOCK_STREAM, 0); if(sock == -1) error_handling("socket() error"); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = inet_addr(argv[1]); serv_adr.sin_port = htons(atoi(argv[2])); if (connect(sock, (struct sockaddr *) &serv_adr, sizeof(serv_adr)) == -1) error_handling("connect() error"); else puts("Connected ..............."); readfp = fdopen(sock, "r"); writefp = fdopen(sock, "w"); while (1) { fputs("Input message(Q to quit): ", stdout); fgets(message, BUF_SIZE, stdin); if (!strcmp(message, "q\n") || !strcmp(message, "Q\n")) break; fputs(message, writefp); fflush(writefp); fgets(message, BUF_SIZE, readfp); printf("Message from server : %s", message); } fclose(writefp); fclose(readfp); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
最後說一句啦。本網絡編程入門系列博客是連載學習的,有興趣的能夠看我博客其餘篇。。。。c++ 網絡編程課設入門超詳細教程 ---目錄
好了今天對網絡編程的學習就到這裏結束了,小飛機我要撤了去吃飯了。,,,不少人大學都很迷茫不知道學點什麼好,,,,,管他的,想那麼多幹嗎,先學了再說,對技術若有偏見,那麼你的領域就侷限於此了---《一專多精》
參考博客:https://blog.csdn.net/u010223072/article/details/48316117
參考博客:https://blog.csdn.net/qq_32103869/article/details/50834629
參考書籍:《TCP/IP 網絡編程 --尹聖雨》