流式套接字C/S通訊程式
阿新 • • 發佈:2018-12-12
客戶端
#include"stdafx.h" #define WIN32_LEAN_AND_MEAN #include<Windows.h> #include<WinSock2.h> #include<WS2tcpip.h> #include<stdlib.h> #include<stdio.h> //連線到winsock2對應的lib檔案:ws2_32.lib,Mswsock.lib,Advapi32.lib #pragma comment (lib,"Ws2_32.lib") #pragma comment (lib,"Mswsock.lib") #pragma comment (lib,"AdvApi32.lib") //定義預設的緩衝區長度和埠號 #define DEFAULT_BUFLEN 512 #define DEFAULT_PORT "27015" int _cdecl main(int argc, char** argv) { WSADATA wsadata; SOCKET Connectsocket = INVALID_SOCKET; struct addrinfo * result = NULL,*ptr = NULL,hints; char *sendbuf = "bryant_xw"; char recvbuf[DEFAULT_BUFLEN]; int iResult; int recvbuflen = DEFAULT_BUFLEN; //驗證引數的合法性 if(argc != 2) { printf("usage:%s server-name\n",argv[0]); return 1; } //初始化套接字 iResult = WSAStartup(MAKEWORD(2,2),&wsadata); if(iResult != 0) { printf("WSAStartup failed with error %d\n",iResult); return 1; } ZeroMemory(&hints,sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; //解析伺服器的地址和埠 iResult = getaddrinfo(argv[1],DEFAULT_PORT,&hints,&result); //成功返回的是0 if(iResult != 0) { printf("GetAddrInfo is failed with error %d\n",iResult); WSACleanup(); return 1; } //嘗試連線伺服器地址,直到成功 for(ptr = result; ptr!=NULL;ptr = ptr->ai_next) { //建立套接字 Connectsocket = socket(ptr->ai_family,ptr->ai_socktype,ptr->ai_protocol); if(Connectsocket == INVALID_SOCKET) { printf("socket failed with error %ld\n",WSAGetLastError()); WSACleanup(); return 1; } //向伺服器發起連線 iResult = connect(Connectsocket,ptr->ai_addr,(int)ptr->ai_addrlen); if(iResult == SOCKET_ERROR) { closesocket(Connectsocket); Connectsocket = INVALID_SOCKET; continue; } break; } freeaddrinfo(result); if(Connectsocket == INVALID_SOCKET) { printf("unable to connect to server"); WSACleanup(); return 1; } //傳送緩衝區的測試資料 iResult = send(Connectsocket,sendbuf,(int)strlen(sendbuf),0); if(iResult == SOCKET_ERROR) { printf("send failed with error %ld\n",WSAGetLastError()); closesocket(Connectsocket); WSACleanup(); return 1; } printf("Bytes sent :%ld\n",iResult); //資料傳送結束,呼叫shutdown函式宣告不再發送資料,但是此時客戶端人可以接收資料 iResult = shutdown(Connectsocket,SD_SEND); if(iResult == SOCKET_ERROR) { printf("shutdown failed with error %ld\n",WSAGetLastError()); closesocket(Connectsocket); WSACleanup(); return 1; } //持續接收資料,直到伺服器關閉連線 do { iResult = recv(Connectsocket,recvbuf,recvbuflen,0); if(iResult > 0) printf("Bytes recevied: %d\n",iResult); else if(iResult == 0) printf("Connection closed\n"); else printf("recv failed with error: %d\n",WSAGetLastError()); } while (iResult > 0); //關閉套接字 closesocket(Connectsocket); //釋放資源 WSACleanup(); return 0; }
伺服器端
#include"stdafx.h" #undef UNICODE #define WIN32_LEAN_AND_MEAN #include<Windows.h> #include<WinSock2.h> #include<WS2tcpip.h> #include<stdlib.h> #include<stdio.h> #pragma comment(lib,"Ws2_32.lib")//連線到Winsock 2 對應的lib檔案:ws2_32.lib //定義預設的緩衝區長度和埠號 #define DEFAULT_BUFLEN 512 #define DEFAULT_PORT "27015" int _cdecl main(void) { WSADATA wsadata; int iResult; SOCKET ListenSocket = INVALID_SOCKET; SOCKET ClientSocket = INVALID_SOCKET; struct addrinfo *result = NULL; struct addrinfo hints; int iSentResult; char recvbuf[DEFAULT_BUFLEN]; int recvbuflen = DEFAULT_BUFLEN; //初始化winsock iResult = WSAStartup(MAKEWORD(2,2),&wsadata); if(iResult != 0) { printf("WSAStartup failed with error:%d\n",iResult); return 1; } ZeroMemory(&hints,sizeof(hints)); //宣告IPv4地址族,流式套接字,TCP協議 hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; //解析伺服器地址和埠號 iResult = getaddrinfo(NULL,DEFAULT_PORT,&hints,&result); //成功返回的是0 if(iResult != 0) { printf("getaddrinfo is failed with error %d\n",iResult); return 1; } //呼叫socket函式建立一個流式套接字 ListenSocket = socket(result->ai_family,result->ai_socktype,result->ai_protocol); if(ListenSocket == INVALID_SOCKET) { printf("socket failed with error %ld\n",WSAGetLastError()); free(result); WSACleanup(); return 1; } //為套接字繫結地址和埠號 iResult = bind(ListenSocket,result->ai_addr,(int)result->ai_addrlen); //成功返回0 if(iResult != 0) { printf("bind failed with error %d\n",WSAGetLastError()); freeaddrinfo(result); closesocket(ListenSocket); WSACleanup(); return 1; } freeaddrinfo(result); //監聽連線請求 iResult = listen(ListenSocket,SOMAXCONN);//成功返回0 if(iResult != 0) { printf("listen failed with error %d\n",WSAGetLastError()); // closesocket(ListenSocket); WSACleanup(); return 1; } //接收客戶端的連線請求,返回 新的 連線套接字 ClientSocket ,之後在ClientSocket上讀寫 ClientSocket = accept(ListenSocket,NULL,NULL); if(ClientSocket == INVALID_SOCKET) { printf("accept failed with error %d\n",WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } //持續接收資料直到對方關連結 do { iResult = recv(ClientSocket,recvbuf,recvbuflen,0); //case 1:成功接收資料 if(iResult > 0) { printf("Bytes received:%d\n",iResult); //將緩衝區的內容回送給客戶端 iSentResult = send(ClientSocket,recvbuf,iResult,0); if(iSentResult == SOCKET_ERROR) { printf("send failed with error %d\n",WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } printf("Bytes sent: %d\n",iSentResult); } //case 2: 連線關閉 else if(iResult == 0) { printf("Connection closing..\n"); } //case3: 接收發生錯誤 else { printf("recv failed with error %d\n",WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } } while (iResult > 0); //關閉連線 iResult = shutdown(ClientSocket,SD_SEND); if(iResult != 0) { printf("shutdown failed with error %d\n",WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } //關閉套接字,釋放資源 closesocket(ClientSocket); WSACleanup(); //在必須要監聽的套接字的情況下釋放該套接字 closesocket(ListenSocket); return 0; }
執行的結果如下圖: