socket學習筆記——易犯錯誤

今天我將分享socket編程,在這條路上的坑,我還能剩多少了!linux

以前再linux系統下進行學習,今天嘗試再window下進行編程;ios

區別:後者須要在進行socket編程,加載socket連接庫。編程

server端:數組

#include<iostream> #include<string> #include<stdlib.h> 
using namespace std; #include<WinSock2.h> #include<Ws2tcpip.h>

#pragma comment(lib,"ws2_32.lib")

#define CONNECT_NUM_MAX 10   //最大鏈接數
#define MSG_MAX_NUM 256        //接受最大數據數
#define MY_PORT 18000        //端口
#define MY_IP 127.0.0.1        //IP

int main() { //0.加載套接字庫
 WSADATA wsaData; int ret = 0; if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) { cout << "WSAStartup(MAKEWORD(2, 2) execute failed!" << endl; return -1; } if (2 != LOBYTE(wsaData.wVersion) || 2 != HIBYTE(wsaData.wVersion)) { WSACleanup(); cout << "WSADATA version is not correct" << endl; return -1; } //1.建立套接字
    SOCKET sockSer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockSer == INVALID_SOCKET) { cout << "sockSer create fail" << endl; return -1; } //初始化服務器地址族變量
 sockaddr_in serAddr; serAddr.sin_family = AF_INET; serAddr.sin_port = htons(18000); serAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); int serLen = sizeof(SOCKADDR); //2.bind連接
    ret = bind(sockSer, (sockaddr *)&serAddr, serLen); if (ret == SOCKET_ERROR) { cout << "bind execute fail" << endl; closesocket(sockSer); WSACleanup(); return -1; } //3.listen監聽
    ret = listen(sockSer, CONNECT_NUM_MAX); if (ret == SOCKET_ERROR) { cout << "listen execute failed" << endl; closesocket(sockSer); return -1; } else { cout << "Server is listening on" << serAddr.sin_addr.s_addr << ":" << serAddr.sin_port << "." << endl; } //4.accept
 sockaddr_in cliAddr; int cliLen = sizeof(SOCKADDR); SOCKET sockCli = accept(sockSer, (sockaddr *)&cliAddr, &cliLen); if (sockCli == INVALID_SOCKET) { cout << "Accepted failed with error code:%d\n" << WSAGetLastError() << endl;; closesocket(sockSer); WSACleanup(); return -1; } cout << "Accepted\n" ; //5.recv/send
    char sendMsg[MSG_MAX_NUM]; char recvMsg[MSG_MAX_NUM]; while (1) { ZeroMemory(recvMsg, MSG_MAX_NUM); //對數組進行初始化
        recv(sockCli, recvMsg, 256,0); cout <<"Cli:>"<<recvMsg << endl; ZeroMemory(sendMsg, MSG_MAX_NUM); cout << "Ser:>"; cin >> sendMsg; send(sockCli, sendMsg, strlen(sendMsg)+1, 0); } //6.close
 closesocket(sockSer); return 0; }

坑1:在服務端,咱們須要兩個SOCKET對象(sockSer和sockCli),前者用來鏈接、監聽和接受客戶端請求;後者則在服務端接受客戶端請求後返回的sockCli,做爲在收發消息的第一個參數。服務器

坑2:必須將客戶端和服務器的端口好進行統一。socket

坑3:sockaddr_in 建立的結構體變量,在配置完成後,connect函數中使用須要進行強轉(sockaddr *).tcp

客戶端:函數

#include<iostream> #include<string> #include<stdlib.h>
using namespace std; #include<WinSock2.h> #include<Ws2tcpip.h>

#pragma comment(lib,"ws2_32.lib")

#define MSG_MAX_NUM 256
#define MY_IP 127.0.0.1
#define MY_PORT 18000


int main() { //0.加載套接字庫
 WSADATA wsaData; int ret = 0; if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) { cout << "WSAStartup(MAKEWORD(2, 2), &wsaData) execute failed" << endl; return -1; } if (2 != LOBYTE(wsaData.wVersion) || 2 != HIBYTE(wsaData.wVersion)) { WSACleanup(); cout << "WSADATA version is not correct" << endl; return -1; } //1.建立套接字
    SOCKET sockCli = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockCli == INVALID_SOCKET) { cout << "sockCli create failed" << endl; } //初始化客戶端連接服務器端變量
 sockaddr_in serAddr; serAddr.sin_family = AF_INET; serAddr.sin_port = htons(MY_PORT); serAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); int serLen = sizeof(sockaddr); //2.connect
    ret = connect(sockCli, (sockaddr *)&serAddr, serLen); if (ret != 0) { cout << "connect failed" << endl; closesocket(sockCli); WSACleanup(); cin.get(); return -1; } //3.收發消息
    char sendMsg[MSG_MAX_NUM]; char recvMsg[MSG_MAX_NUM]; while (1) { ZeroMemory(sendMsg, MSG_MAX_NUM); cout << "Cli:>"; cin >> sendMsg; send(sockCli, sendMsg, strlen(sendMsg) + 1, 0); ZeroMemory(recvMsg, MSG_MAX_NUM); recv(sockCli, recvMsg, 256, 0); cout << "Ser:>" << recvMsg << endl; } //4.關閉套接字
 closesocket(sockCli); return 0; }

坑1:客戶端只要一個SOCKET對象,即針對服務端進行鏈接,發送數據;學習

坑2:sockaddr_in 建立的結構體變量,在配置完成後,connect函數中使用須要進行強轉(sockaddr *).大數據

相關文章
相關標籤/搜索