程式設計訓練Day002——基於TCP的Socket程式設計
阿新 • • 發佈:2018-12-18
這個程式算是這輩子寫的第一個完整的程式,不是今天一天寫的,之前花了四五天,不到四百行的程式碼對程式設計老鳥來說估計是分分鐘的事,但我還是挺知足的,畢竟第一次。
真正自己嘗試寫一個程式之後才發現,之前看的所有的東西都是紙上談兵,只有自己動手寫一個程式,才會理解什麼叫程式設計,從程式設計到程式編寫到程式除錯到功能優化,很多東西都是書本上學不到的。
這個程式主要實現的功能簡單的說就是TCP通訊,在通訊之上實現雙機協同工作,執行環境是windows。
貼程式碼:
#define _CRT_SECURE_NO_WARNINGS #pragma comment(lib, "ws2_32.lib") #include <windows.h> #include <time.h> #include <stdlib.h> #include <stdio.h> #define PORT 8888 /*定義埠*/ #define MAXDATA 1000 /*定義最大傳輸數量*/ #define T 100 int exe(void) { long i = 100000000L; while (i--); printf(" This is a program that needs to be executed !\n"); return 0; } int main(void) { /*各種宣告定義*/ SOCKET server; SOCKET client; struct sockaddr_in serveraddr; struct sockaddr_in clientaddr; WSADATA wsaData; int len = sizeof(struct sockaddr_in); int runTime, serverTime_i, clientTime_i, ret_1, ret_cyc, ret_time_server, ret_time_client; int dec_1, sign_1, dec_2, sign_2; int t = T; int con = -1; char port; char receiveData[MAXDATA]; char runData[MAXDATA]; char *readyMessage_server = "I'm ready !\n"; char *readyMessage_client = "I'm ready too !\n"; char *runMessage = "Run !\n"; char serverTime_c[MAXDATA], *serverTime_c_server, clientTime_c[MAXDATA], *clientTime_c_client; char waitTime, serverTime_d, clientTime_d; clock_t start, end; /*選擇伺服器或客戶端*/ printf("Please choose server of client.\nA.Server B.Client\n"); scanf("%c", &port); /*伺服器*/ if (port == 'A' || port == 'a') { /*啟動windows的socket服務,初始化WSA*/ WSAStartup(0x101, &wsaData); /*建立服務端,初始化伺服器地址*/ memset((void *)&serveraddr, 0, sizeof(serveraddr)); /*建立伺服器套接字*/ server = socket(AF_INET, SOCK_STREAM, 0); if (server == -1) { printf("Socket error !"); } /*繫結IP和埠*/ serveraddr.sin_family = AF_INET; /*定義家族協議*/ serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1"); /*定義主機地址*/ serveraddr.sin_port = htons(PORT); /*定義主機埠*/ if (bind(server, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1) /*繫結成功返回0*/ { printf("Bind error !"); getchar(); exit(1); } /*開始監聽*/ if (listen(server, 20) == -1) { printf("Listen error !"); getchar(); exit(1); } /*建立連線*/ printf("Waiting for connection...\n\n"); client = accept(server, (SOCKADDR *)&clientaddr, &len); if (client == -1) { printf("accept error !"); getchar(); exit(1); } printf("Receive a connection: %s \r\n\n", inet_ntoa(clientaddr.sin_addr)); /*傳送準備資訊*/ if (send(client, readyMessage_server, strlen(readyMessage_server), 0) < 0) { printf("\n\nSend error or connection interruption !\n"); getchar(); exit(1); } /*接受準備資訊*/ int ret_1 = recv(client, receiveData, MAXDATA, 0); if (ret_1 > 0) { receiveData[ret_1] = 0x00; printf("From client %s: %s", inet_ntoa(clientaddr.sin_addr), receiveData); } /*接收不到客戶端資料時中斷迴圈*/ else { printf("\n\nReceive error or connection interruption !\n"); getchar(); exit(1); } /*發出執行許可指令*/ if (strcmp(receiveData, readyMessage_client) == 0) { ; if (send(client, runMessage, strlen(runMessage), 0) < 0) { printf("\n\nSend error or connection interruption !\n"); getchar(); exit(1); } } while (1) { /*執行時間大於週期時間,則直接執行*/ if (t >= T) { /*計時開始*/ start = clock(); exe(); /*計時結束*/ end = clock(); /*服務端執行用時*/ serverTime_d = (double)(end - start); /*服務端執行用時轉字串*/ _ecvt(serverTime_d, 10, &dec_1, &sign_1); serverTime_c_server = _ecvt(serverTime_d, dec_1, &dec_2, &sign_2); printf("Operation time is %s\n\n", serverTime_c_server); /*傳送服務端執行用時*/ if (send(client, serverTime_c_server, strlen(serverTime_c_server), 0) < 0) { printf("\n\nSend error or connection interruption !\n"); getchar(); exit(1); } /*接收客戶端執行用時*/ ret_time_client = recv(client, clientTime_c, MAXDATA, 0); if (ret_time_client > 0) { clientTime_c[ret_time_client] = 0x00; } else { printf("\n\nReceive error or connection interruption !\n"); getchar(); exit(1); } /*字串轉整形*/ serverTime_i = atoi(serverTime_c_server); printf("Server's operation time is %d\n", serverTime_i); clientTime_i = atoi(clientTime_c); printf("Client's operation time is %d\n", clientTime_i); /*比較服務端、客戶端用時長短*/ if (serverTime_i >= clientTime_i) { runTime = serverTime_i; } else { runTime = clientTime_i; } t = runTime; printf("The whole system's opration time is %d\n\n", t); /*執行總時長小於週期時間,掛起*/ if (t <= T) { waitTime = T - t; Sleep(waitTime); t = T; } } } /*客戶端關閉,提示連線中斷*/ printf("Connection interruption !\n"); getchar(); exit(1); } /*客戶端*/ else { /*啟動windows的socket服務,初始化WSA*/ WSAStartup(0x101, &wsaData); /*建立服務端,初始化伺服器地址*/ memset((void *)&clientaddr, 0, sizeof(clientaddr)); /*建立伺服器套接字*/ client = socket(AF_INET, SOCK_STREAM, 0); if (client == -1) { printf("Socket error !"); getchar(); exit(1); } /*繫結IP和埠*/ clientaddr.sin_family = AF_INET; /*定義家族協議*/ clientaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); /*定義主機地址*/ clientaddr.sin_port = htons(PORT); /*定義主機埠*/ while (1) { /*連線中斷,跳出迴圈,提示連線中斷*/ if (con == 1) { break; } /*啟動程式時迴圈連線服務端*/ while (con == -1) { con = connect(client, (struct sockaddr *)&clientaddr, sizeof(clientaddr)); if (con == -1) { printf("Connection error !\n"); } } /*接收準備資訊*/ ret_1 = recv(client, receiveData, MAXDATA, 0); if (ret_1 > 0) { receiveData[ret_1] = 0x00; printf("From server: %s", receiveData); } /*接受不到客戶端資料時中斷迴圈*/ else { printf("\n\nReceive error or connection interruption !\n"); getchar(); exit(1); } /*傳送準備資訊*/ if (send(client, readyMessage_client, strlen(readyMessage_client), 0) < 0) { printf("\n\nSend error or connection interruption !\n"); getchar(); exit(1); } /*接收執行許可指令*/ ret_cyc = recv(client, runData, MAXDATA, 0); if (ret_cyc > 0) { runData[ret_cyc] = 0x00; printf(runData); } /*接收不到服務端資料時中斷迴圈*/ else { printf("\n\nReceive error or connection interruption !\n"); getchar(); exit(1); } /*檢驗執行許可指令並開始執行*/ if (strcmp(runData, runMessage) == 0) { while (con == 0) { if (t >= T) { /*計時開始*/ start = clock(); exe(); /*計時結束*/ end = clock(); /*客戶端執行用時*/ clientTime_d = (double)(end - start); /*服務端執行用時轉字串*/ _ecvt(clientTime_d, 10, &dec_1, &sign_1); clientTime_c_client = _ecvt(clientTime_d, dec_1, &dec_2, &sign_2); printf("Operation time is %s\n\n", clientTime_c_client); /*傳送服務端執行用時*/ if (send(client, clientTime_c_client, strlen(clientTime_c_client), 0) < 0) { printf("\n\nSend error or connection interruption !\n"); getchar(); exit(1); } /*接收客戶端執行用時*/ ret_time_server = recv(client, serverTime_c, MAXDATA, 0); if (ret_time_server > 0) { serverTime_c[ret_time_server] = 0x00; } else { printf("\n\nReceive error or connection interruption !\n"); getchar(); exit(1); } /*字串轉整形*/ serverTime_i = atoi(serverTime_c); printf("Server's operation time is %d\n", serverTime_i); clientTime_i = atoi(clientTime_c_client); printf("Client's operation time is %d\n", clientTime_i); /*比較服務端、客戶端用時長短*/ if (serverTime_i >= clientTime_i) { runTime = serverTime_i; } else { runTime = clientTime_i; } t = runTime; printf("The whole system's opration time is %d\n\n", t); /*執行總時長小於週期時間,掛起*/ if (t <= T) { waitTime = T - t; Sleep(waitTime); t = T; } } } } } /*客戶端關閉,提示連線中斷*/ printf("Connection interruption !\n"); getchar(); exit(1); } return 0; }
因為是寫了很多天的一個程式了,功能基本能想到的都優化過了,學到的東西真的很多,大概列一列吧:
- Socket程式設計的思路,其中各個函式的含義
- 資料傳輸的阻塞和非阻塞
- 資料儲存的大小端(位元組序)
- char *a和char a[]的區別
- VS到底該怎麼用
- 其實還有很多,這些只是我暫時能想到的
其實今天是偷懶了,本來想把昨天的計算器程式完善一下的,但因為工作需要,就先這個程式收了個尾,不過加的程式碼應該超過百行了,明天繼續,希望自己可以堅持。