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 *).大数据

相关文章
相关标签/搜索