在学校浅浅地学习了计网这门课,更多地是关注路由算法这些等等。没怎么接触网络编程这一块。
最近找到一个实习,本来是要学习IOCP模型的。但是我连基础的收发消息都没有实现过。因此在一番搜索学习后个人实现了简易的windows平台下的阻塞式双线程服务器,当然了也实现了客户端。
这就将代码贴上来给大家参考,主要是发现网上的代码大多都有点冗杂。所以将个人认为比较简洁的代码展示出来。
服务器代码:
//simpleServer.cpp #include<WinSock2.h> #include<Windows.h> #include<process.h> #include<iostream> #pragma comment (lib, "ws2_32.lib") using namespace std; typedef struct myPara //我设这个结构体只是为了方便传更多参数到子线程以便debug { SOCKET ClientSocket; sockaddr_in clntAddr; int id; }MyPara; DWORD WINAPI MyThreadPro(const LPVOID param)//子线程执行函数 { MyPara *temp = (MyPara*) param; int my_id = temp->id; cout << my_id << "线程:测试开始, 等待客户端发送数据。 id地址:" << &(temp->id) << " 客户端端口号:" << ntohs(temp->clntAddr.sin_port) <<endl; //从客户端接受数据 char szBuffer[MAXBYTE] = {0}; recv(temp->ClientSocket,szBuffer,MAXBYTE,NULL); cout << my_id << "线程:从客户端接受到:" << szBuffer << " temp->id:" << temp->id << " 客户端端口号:" << ntohs(temp->clntAddr.sin_port) <<endl; //向客户端发送数据 char *str = "你好我是服务器"; send(temp->ClientSocket, str, strlen(str)+sizeof(char), NULL); cout << my_id << "线程:成功向客户端发送数据" << " temp->id:" << temp->id << " 客户端端口号:" << ntohs(temp->clntAddr.sin_port)<< endl; return 0; } int main() { WSADATA wsaData;//初始化dll WSAStartup(MAKEWORD(2,2), &wsaData); //创建套接字 SOCKET servSock = socket(PF_INET, SOCK_STREAM, 0); //设置各种条件然后和套接字绑定在一起 sockaddr_in sockAddr; memset(&sockAddr,0,sizeof(sockAddr)); sockAddr.sin_family = PF_INET; sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); sockAddr.sin_port = htons(1234); bind(servSock, (SOCKADDR *)&sockAddr, sizeof(SOCKADDR)); //获得线程的句柄 HANDLE hThread[2]; listen(servSock, 20); for(int i = 0; i < 2; i ++) { MyPara *temp = new MyPara; sockaddr_in clntAddr; int nSize = sizeof(SOCKADDR); SOCKET clntSock = accept(servSock, (SOCKADDR *)&clntAddr, &nSize); temp->ClientSocket = clntSock; temp->id = i+1; temp->clntAddr = clntAddr; cout << temp << endl; hThread[i] = CreateThread(NULL,0,&MyThreadPro,temp,0,NULL); } WaitForMultipleObjects(2, hThread, TRUE, INFINITE); //关闭套接字 closesocket(servSock); cout << "线程全部执行完毕" << endl; system("pause"); //终止 DLL 的使用 WSACleanup(); return 0; }
客户端代码:
#include <iostream> #include <WinSock2.h> #pragma comment(lib, "ws2_32.lib") //加载 ws2_32.dll using namespace std; int main(){ //初始化DLL WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); //创建套接字 SOCKET sock = socket(PF_INET, SOCK_STREAM, 0); //向服务器发起请求 sockaddr_in sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充 sockAddr.sin_family = PF_INET; sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); sockAddr.sin_port = htons(1234); connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR)); cout << "测试开始" << endl; system("pause"); //向服务器发送数据 char *str = new char[100]; cout << "请输入发送内容:" << endl; cin >> str; send(sock, str, strlen(str)+sizeof(char), NULL); cout << "成功向服务器发送数据" << endl; system("pause"); //接收服务器传回的数据 char szBuffer[MAXBYTE] = {0}; recv(sock, szBuffer, MAXBYTE, NULL); //输出接收到的数据 //printf("Message form server: %s\n", szBuffer); cout << "Message form server: " << szBuffer << endl; //关闭套接字 closesocket(sock); //终止使用 DLL WSACleanup(); system("pause"); return 0; }
客户端代码比服务器代码简单很多,因为少了绑定套接字到串口等等步骤。先运行服务器,然后在运行两个客户端(同一份exe文件)。具体整个流程我就不解释了,相信来到这里的人都是了解了整个流程的。然后强调一点是这份代码得在VS的环境下跑,我在dev无论怎么设置连接库等等都不成功。
鄙人只是初出茅庐的菜鸟,如有不足,多多见谅。