Windows网络通信(Socket)入门代码

来源:互联网 发布:剑灵人族捏脸数据2016 编辑:程序博客网 时间:2024/05/16 08:01

随便写写,非常简单,可以作为网络通信入门代码。

代码分为两部分:一个服务端;一个客户端。分别建立两个工程,直接编译运行就可以见到效果!

其中用到了多线程的一些技术,关于线程同步这方面暂未考虑!

/************************************************************************//*Server.cpp                                                            *//************************************************************************/#include <WinSock2.h>#include <iostream>#include <string>#include <process.h>#include <list>//using namespace std;//#pragma comment (lib, "wsock32.lib")//或者 连接器-》输入-》附加依赖项中加入wsock32.lib#pragma comment (lib, "WS2_32.lib")#define MAXBUF 32767int nFlag = 1;//0表示退出std::list<SOCKET> ConnSocketLst;SOCKETListeningSocket;//接受数据UINT WINAPI RecvData(LPVOID pParam);//发送数据UINT WINAPI SendData(LPVOID pParam);int main(){WSADATAWsaData;//SOCKETListeningSocket;//SOCKETNewConnectSocket;SOCKADDR_INServerAddr;SOCKADDR_INClientAddr;intPort = 5678;//初始化版本2.2if (0 != WSAStartup(MAKEWORD(2, 2), &WsaData)){std::cout << "网络初始化失败\n";getchar();return -1;}//创建一个新的套接字来监听客户机的连接ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//建立一个SOCKADDR_IN结构,来告知bind函数要在5678端口上监听所有接口的连接ServerAddr.sin_family = AF_INET;ServerAddr.sin_port = htons(Port);//主机字节顺序转换为网络字节顺序ServerAddr.sin_addr.s_addr = htonl(ADDR_ANY);//使用bind函数将这个地址信息与套接字关联起来bind(ListeningSocket, (SOCKADDR*)&ServerAddr, sizeof(SOCKADDR));//监听客户机listen(ListeningSocket, 5);//得到尺寸int ClientLen = sizeof(SOCKADDR_IN);//创建线程,发送数据HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, SendData, NULL, 0, NULL);//循环得到客户端的连接while(0 != nFlag){//连接到达时接受一个新连接SOCKET NewConnectSocket = accept(ListeningSocket, (SOCKADDR*)&ClientAddr, &ClientLen);ConnSocketLst.push_back(NewConnectSocket);//创建线程,接受数据HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, RecvData, (LPVOID)(&NewConnectSocket), 0, NULL);}//关闭套接字std::list<SOCKET>::iterator it = ConnSocketLst.begin();for (; it != ConnSocketLst.end();){closesocket(*it);ConnSocketLst.erase(it++);}ConnSocketLst.clear();closesocket(ListeningSocket);//清理WSACleanup();getchar();return 0;}//接受数据UINT WINAPI RecvData(LPVOID pParam){//得到套接字SOCKET Socket = *((SOCKET*)pParam);//获得数据char buf[MAXBUF] = {0};while (1){int nLen = recv(Socket, buf, MAXBUF, 0);// | MSG_PEEK | MSG_OOB);if (0 < nLen){buf[nLen] = '\0';std::cout << buf << "\n";SendData(buf);//是否退出if (0 == strcmp(buf, "客户端:\n  quit\n")){break;}}else{std::cout << "接收数据失败\n";break;}}closesocket(Socket);ConnSocketLst.remove(Socket);/*std::list<SOCKET>::iterator it = ConnSocketLst.begin();for (; it != ConnSocketLst.end(); it++){if (*it == Socket){ConnSocketLst.erase(it);break;}}*///_endthreadex(0);return 0;}//发送数据UINT WINAPI SendData(LPVOID pParam){//得到套接字char *SendBuf = (char*)pParam;if (SendBuf == NULL){//将要发送的数据std::string strSend;//循环输入并发送数据while (0 != nFlag){//清空以前的数据并重新输入数据strSend.clear();for (;;){char cTemp = getchar();strSend.append(1, cTemp);if (cTemp == '\n') {strSend.append(1, '\0');break;}}//设置标志(是否退出)nFlag = strcmp(strSend.c_str(), "quit\n");//发送数据前准备strSend = "服务端:\n  " + strSend;//std::cout << strSend.c_str() << "\n";int nLeft = (int)strSend.length();//发送数据std::list<SOCKET>::iterator it = ConnSocketLst.begin();for (; it != ConnSocketLst.end(); it++){int nRet = send(*it, strSend.c_str(), nLeft, 0);// | MSG_DONTROUTE | MSG_OOB);if (nRet == SOCKET_ERROR) {std::cout << "发送数据失败\n";}}}//关闭监听套接字closesocket(ListeningSocket);}else{int nLeft = (int)strlen(SendBuf);//发送数据std::list<SOCKET>::iterator it = ConnSocketLst.begin();for (; it != ConnSocketLst.end(); it++){int nRet = send(*it, SendBuf, nLeft, 0);// | MSG_DONTROUTE | MSG_OOB);if (nRet == SOCKET_ERROR) {std::cout << "发送数据失败\n";}}}return 0;}/************************************************************************//*Client.cpp                                                            *//************************************************************************/#include <WinSock2.h>#include <iostream>#include <string>#include <process.h>#pragma comment (lib, "WS2_32.lib")#define MAXBUF 32767intnFlag = 1;//0表示退出HANDLEg_Mutex = CreateMutex(NULL, TRUE, NULL);//创建互斥对象//接受数据UINT WINAPI RecvData(LPVOID pParam);//发送数据UINT SendData(LPVOID pParam);int main(){WSADATAWsaData;SOCKETClientSocket;SOCKADDR_INServerAddr;intPort = 5678;//初始化版本2.2if (0 != WSAStartup(MAKEWORD(2, 2), &WsaData)){std::cout << "网络初始化失败\n";goto END;}//创建一个新的套接字来建立客户机的连接ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//建立一个SOCKADDR_IN结构,来连接服务器ServerAddr.sin_family = AF_INET;ServerAddr.sin_port = htons(Port);//主机字节顺序转换为网络字节顺序ServerAddr.sin_addr.s_addr = inet_addr(("127.0.0.1"));//用套接字创建一个到服务器的连接if (0 != connect(ClientSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr))){std::cout << "连接服务器失败\n";goto END;}//创建线程,接受数据HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, RecvData, (LPVOID)(&ClientSocket), 0, NULL);//发送数据SendData(&ClientSocket);//等待接收数据的线程结束while (WAIT_OBJECT_0 != WaitForSingleObject(hThread, INFINITE)) { }END://关闭套接字closesocket(ClientSocket);//清理WSACleanup();//释放互斥对象ReleaseMutex(g_Mutex);getchar();return 0;}//接受数据UINT WINAPI RecvData(LPVOID pParam){//得到套接字SOCKET Socket = *((SOCKET*)pParam);//获得数据char buf[MAXBUF] = {0};while (1){int nLen = recv(Socket, buf, MAXBUF, 0);// | MSG_PEEK | MSG_OOB);if (0 < nLen){buf[nLen] = '\0';std::cout << buf << "\n";//是否退出if (0 == strcmp(buf, "服务端:\n  quit\n")){break;}}else{std::cout << "与服务器断开连接\n";break;}}nFlag = 0;return 0;}//发送数据UINT SendData(LPVOID pParam){//得到套接字SOCKET Socket = *((SOCKET*)pParam);//将要发送的数据std::string strSend;//循环输入并发送数据while (0 != nFlag){//清空以前的数据并重新输入数据strSend.clear();for (;;){char cTemp = getchar();strSend.append(1, cTemp);if (cTemp == '\n') {strSend.append(1, '\0');break;}}//发送数据前准备strSend = "客户端:\n  " + strSend;int nLeft = (int)strSend.length();int nRet = send(Socket, strSend.c_str(), nLeft, 0);// | MSG_DONTROUTE | MSG_OOB);if (nRet == SOCKET_ERROR) {std::cout << "发送数据失败\n";}}return 0;}