服務端(server)
#include <stdio.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") //把ws2_32.lib加到Link頁的連接庫 #define PORT 15001 //通信的端口(指服務器端) #define ERROR 0 #define BUFFER_SIZE 1024 //注意:此Server端數據接收緩沖區 >= Client端數據發送緩沖區 ,否則造成緩沖區溢出 /* 服務端原理: 1、服務器進程創建套接字 2、將本地地址綁定到所創建的套接字上,以三元組{<通信協議>,<IP地址>,<端口號>}在網絡上標識該套接字 3、將套接字置入監聽模式,並准備接受連接請求 4、接受請求之后,便可接收客戶端發來的數據,並以本地DOS命令運行 */ int main() { WSADATA WSAData; if(WSAStartup(MAKEWORD(2,0),&WSAData)==SOCKET_ERROR) //啟動winsock ,WSAStartup()函數對Winsock DLL進行初始化 { printf("Socket initialize fail!\n"); exit(1); } SOCKET sock; //服務進程創建套接字句柄(用於監聽) if((sock=socket(AF_INET,SOCK_STREAM,0))==ERROR) //調用socket()函數創建一個流套接字,參數(網絡地址類型,套接字類型,網絡協議) { printf("Socket create!\n"); WSACleanup(); exit(1); } struct sockaddr_in ServerAddr; //sockaddr_in結構用來標識TCP/IP協議下的地址,可強制轉換為sockaddr結構 ServerAddr.sin_family=AF_INET; //sin_family字段必須設為AF_INET,表示該Socket處於Internet域 ServerAddr.sin_port=htons(PORT); //sin_port字段用於指定服務端口,注意避免沖突 ServerAddr.sin_addr.s_addr=INADDR_ANY; //sin_addr字段用於把一個IP地址保存為一個4字節的數,無符號長整型,根據不同用法還可表示本地或遠程IP地址 if(bind(sock,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr))==SOCKET_ERROR) //調用bind()函數將本地地址綁定到所創建的套接字上,以在網絡上標識該套接字 { printf("Bind fail!\n"); closesocket(sock); WSACleanup(); exit(1); } printf("Server Socket Port:%d\n",ntohs(ServerAddr.sin_port)); if(listen(sock,10)==SOCKET_ERROR) //調用listen()函數將套接字置入監聽模式並准備接受連接請求,參數(已捆綁未連接的套接字描述字,正在等待連接的最大隊列長度) { printf("Listen fail!\n"); closesocket(sock); WSACleanup(); exit(1); } SOCKET msgsock; //創建一個新的套接字(用於接收accept函數的返回值,即表示已經接受的那個客戶端的連接,進而接收Client發來的數據) char buf[BUFFER_SIZE]; //數據接收緩沖區 while(1) { if((msgsock=accept(sock,(LPSOCKADDR)0,(int *)0))==INVALID_SOCKET) //進入監聽狀態后,調用accept()函數接收客戶端的連接請求,並把連接傳給msgsock套接字,原sock套接字繼續監聽其他客戶機連接請求 { printf("Accept fail!\n"); continue; } memset(buf,0,sizeof(buf)); //初始化數據接收緩沖區 recv(msgsock,buf,BUFFER_SIZE,0); //接收客戶端發送過來的數據 if(buf[0]=='e' && buf[1]=='x' && buf[2]=='i' && buf[3]=='t') //"exit"命令,退出程序 { printf("The End.\n"); break; } printf("C:\\Socket\\Server>%s",buf); system(buf); //本地運行客戶端傳來的命令:這一點太厲害了,假如傳一個Format命令,那服務端可能就毀了 closesocket(msgsock); } closesocket(sock); //關閉套接字 WSACleanup(); //終止對Winsock DLL的使用,並釋放資源 return 0; }
客戶端(client)
#include <winsock2.h> #include <stdio.h> #pragma comment(lib,"ws2_32.lib") //把ws2_32.lib加到Link頁的連接庫 //#define IP "172.18.68.243" //在兩台計算機上測試,IP為Server端的IP地址 #define IP "127.0.0.1" //在一台計算機上測試,IP為本地回送地址 #define PORT 15001 //注意:客戶端設置通信的端口 = 服務端的端口 #define BUFFER_SIZE 1024 //數據發送緩沖區大小 /* 客戶端原理: 1、客戶端進程創建套接字 2、客戶端向服務端進程發出連接請求 3、當服務端接受請求后,客戶端便可向服務端發送數據 */ int main() { char buf[BUFFER_SIZE]; //buf數組存放客戶端發送的消息 int inputLen; //用於輸入字符自增變量 while(1) { printf("C:\\Socket\\Client>"); inputLen=0; memset(buf,0,sizeof(buf)); while((buf[inputLen++]=getchar())!='\n') //輸入以回車鍵為結束標識 { ; } if(buf[0]=='e' && buf[1]=='x' && buf[2]=='i' && buf[3]=='t') { printf("The End.\n"); break; } WSADATA WSAData; if(WSAStartup(MAKEWORD(2,0),&WSAData)==SOCKET_ERROR) //WSAStartup()函數對Winsock DLL進行初始化 { printf("Socket initialize fail!\n"); continue; } SOCKET sock; //客戶端進程創建套接字 if((sock=socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR) //創建流套接字(與服務端保持一致) { printf("Socket create fail!\n"); WSACleanup(); continue; } struct sockaddr_in ClientAddr; //sockaddr_in結構用來標識TCP/IP協議下的地址,可強制轉換為sockaddr結構 ClientAddr.sin_family=AF_INET; //指Internet域 ClientAddr.sin_port=htons(PORT); //指定服務端所預留的端口 ClientAddr.sin_addr.s_addr=inet_addr(IP); //指定服務端所綁定的IP地址 if(connect(sock,(LPSOCKADDR)&ClientAddr,sizeof(ClientAddr))==SOCKET_ERROR) //調用connect()函數,向服務器進程發出連接請求 { printf("Connect fail!\n"); closesocket(sock); WSACleanup(); continue; } send(sock,buf,BUFFER_SIZE,0); //向服務器發送數據 closesocket(sock); //關閉套接字 WSACleanup(); //終止對Winsock DLL的使用,並釋放資源,以備下一次使用 } return 0; }
客戶端的簡單寫法
#include <winsock2.h> #include <stdio.h> #pragma comment(lib,"ws2_32.lib") //把ws2_32.lib加到Link頁的連接庫 //#define IP "172.18.68.243" //在兩台計算機上測試,IP為Server端的IP地址 #define IP "127.0.0.1" //在一台計算機上測試,IP為本地回送地址 #define PORT 6666 //注意:客戶端設置通信的端口 = 服務端的端口 int main() { WSADATA WSAData; SOCKET sock; WSAStartup(MAKEWORD(2, 0), &WSAData); //== SOCKET_ERROR) WSAStartup()函數對Winsock DLL進行初始化 sock = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in ClientAddr; //sockaddr_in結構用來標識TCP/IP協議下的地址,可強制轉換為sockaddr結構 ClientAddr.sin_family = AF_INET; //指Internet域 ClientAddr.sin_port = htons(PORT); //指定服務端所預留的端口 ClientAddr.sin_addr.s_addr = inet_addr(IP); //指定服務端所綁定的IP地址 connect(sock, (LPSOCKADDR)&ClientAddr, sizeof(ClientAddr)); closesocket(sock); //關閉套接字 WSACleanup(); //終止對Winsock DLL的使用,並釋放資源,以備下一次使用 return 0; }
參考文獻:https://blog.csdn.net/lynch0571
