/*-------------------------------------------------------------*/ /* 程式名稱 : tcp_echocli_01.c */ /* 程式版本 : 20041229.01 */ /* 修改日期 : 2004/12/29 */ /* 對應程式 : tcp_echosrv_01.c */ /* 程式執行 : tcp_echocli_01 serverip portno */ /* 程式說名 : 簡單的 IPv4 TCP ECHO CLIENT 端程式 */ /* 當 tcp_echocli_01 連上 tcp_echosrv_01 後 */ /* 由使用者從鍵盤輸入ECHO字串後,將ECHO字串以XOR加密 */ /* 將ECHO字串傳給 tcp_echosrv_01 */ /* 再由 tcp_echocli_01 接收從 tcp_echosrv_01 */ /* 傳回給的 ECHO字串並以XOR解密還原 */ /* 最後關閉 TCP 網路連線 */ /*-------------------------------------------------------------*/ #include #include #include #include #include #include #define STR_MAX 1024 #define SOCKET_ERROR -1 char *data_xor(char *pdata, int len, unsigned char cKey) { int i ; char *p ; p = pdata ; for (i=0;ih_addr,pSrvInfo->h_length); srvSockaddr.sin_port= htons(nSrvPort); srvSockaddr.sin_family=AF_INET; printf("\n[004]嘗試與伺服端[%s:%d]建立TCP連線",strSrvHost, nSrvPort); nRetValue = connect(cliSock,(struct sockaddr*)&srvSockaddr,sizeof(srvSockaddr)) ; if (nRetValue == SOCKET_ERROR) { printf("\n[ERR]無法與伺服端建立TCP連線\n") ; return 0 ; } printf("\n[005]已經與伺服端建立IPv4 TCP連線") ; /* 擷取客戶端 socket 連線的實際 IP位址與 Port */ while (1) { getsockname(cliSock, (struct sockaddr*)&cliSockaddr, &nsockaddrsize) ; inet_ntop(AF_INET, &cliSockaddr.sin_addr, strLocalHost, sizeof(strLocalHost)) ; nLocalPort = ntohs(cliSockaddr.sin_port) ; if (cliSockaddr.sin_family == AF_INET) { break ; } else { printf("\n[WRN]尚未取得客戶端socket的TCP連線資訊[%s:%d]", strLocalHost, nLocalPort) ; } } /* 擷取伺服端 socket 連線的實際 IP位址與 Port */ while (1) { getpeername(cliSock, (struct sockaddr*)&peerSockaddr, &nsockaddrsize) ; inet_ntop(AF_INET, &peerSockaddr.sin_addr, strPeerHost, sizeof(strPeerHost)) ; nPeerPort = ntohs(peerSockaddr.sin_port) ; if (peerSockaddr.sin_family == AF_INET) { break ; } else { printf("\n[WRN]尚未取得伺服端socket的TCP連線資訊[%s:%d]", strPeerHost, nPeerPort) ; } } printf("\n[006]此TCP連線建立在客戶端[%s:%d]伺服端[%s:%d]之間", strLocalHost, nLocalPort, strPeerHost, nPeerPort) ; printf("\n[007]請輸入ECHO訊息:") ; /* 使用者從鍵盤輸入ECHO字串 */ memset(strInput, '\0', STR_MAX) ; fgets(strInput, STR_MAX, stdin) ; strInput[strlen(strInput)-1] = '\0' ; /* 將換行字元'\n' 換成字串終止字元'\0' */ printf("\n[008]將ECHO訊息(長度:%d)送至伺服端:\"%s\"", strlen(strInput), strInput) ; data_xor(strInput, strlen(strInput), 0xBA) ; nRetValue = send(cliSock, strInput, strlen(strInput), 0) ; if (nRetValue == SOCKET_ERROR) { printf("\n[ERR]無法送ECHO訊息至伺服端\n"); close(cliSock) ; return 0; } printf("\n[009]已把ECHO訊息送至伺服端") ; printf("\n[010]等待從伺服端送回的ECHO訊息") ; memset(strEcho, 0, STR_MAX) ; /* 將 ECHO 字串清空 */ nByteRead = recv(cliSock, strEcho, STR_MAX, 0) ; if (nByteRead == SOCKET_ERROR) { printf("\n[ERR]無法接收從伺服端送來的ECHO訊息\n"); close(cliSock) ; return 0; } data_xor(strEcho, nByteRead, 0xBA) ; printf("\n[011]已從伺服端接收ECHO訊息(長度%d):\"%s\"", strlen(strEcho), strEcho) ; printf("\n[012]關閉客戶端的 socket\n") ; close(cliSock) ; }