主机字节顺序转网络字节顺序 #include "stdafx.h" #include "WinSock2.h" //包含WinSock库头文件 #include "iostream" #pragma comment(lib, "ws2_32.lib") //链接WinSock导入库 using namespace std; int main(int argc, char **argv) { WSADATA wsaData; WORD wVersionRequested = MAKEWORD(2,2); if(WSAStartup(wVersionRequested,&wsaData)!=0) { cout<<"加载WinSock DLL失败!\n"; return 0; } u_short x, y=0x1234; //定义无符号短整型变量x、y,并将y初始化为十六进制数0x1234 x=htons(y); //将y的值转换为网络字节顺序并将转换结果存入变量x //ntohs()网到主 cout<< "主机字节顺序:"<<hex<<y<< "\t网络字节顺序:"<<x<<endl; u_long a, b=0x1122ABCD; //定义无符号长整型变量a、b,并将b初始化 a= htonl(b); //将b的值转换为网络字节顺序并将转换结果存入变量a //ntohl()网到主 cout<< "主机字节顺序:"<<hex<<b<<"\t网络字节顺序:"<<a<<endl; WSACleanup(); //注销WinSock DLL return 0; } 查询主机的名称、IP,输入域名并解析 #include "stdafx.h" #include "WinSock2.h" //包含WinSock库头文件 #include "iostream" #pragma comment(lib, "ws2_32.lib") //链接WinSock导入库 using namespace std; int main(int argc, char **argv) { struct hostent *hptr; char **pptr; char hostname[256]; //用于存放获取的本机名称或输入的远程主机域名 /***初始化WinSock DLL***/ WSADATA wsaData; WORD wVersionRequested =MAKEWORD(2,2); //生成版本号2.2 if(WSAStartup(wVersionRequested,&wsaData)!=0) { cout<<"加载WinSock DLL失败!\n"; return 0; } if( gethostname(hostname,sizeof(hostname)) ) //获取本机名字 { cout<<"获取主机名字失败!\n"<<endl; WSACleanup(); return 0; } cout<<"本机名字为:"<<hostname<<endl; if( (hptr = gethostbyname(hostname)) == NULL) //获取本机IP地址 { cout<<"通过主机名获取本机IP地址失败!\n"<<endl; WSACleanup(); return 0; } /***输出IP地址***/ pptr=hptr->h_addr_list; cout<<"本机IP地址:"<<endl; while(*pptr!=NULL) { cout<< inet_ntoa(*(struct in_addr *) (*pptr))<<endl; //长整型的Ip->点分十进制 pptr++; } /***从键盘输入要解析的网站的域名***/ cout <<"输入要解析的域名:"<<endl; cin>>hostname; if( (hptr = gethostbyname(hostname)) == NULL) //解析输入的网站域名 { cout<<"名字解析失败!\n"<<endl; WSACleanup(); return 0; } /***输出远程机器IP地址***/ pptr=hptr->h_addr_list; cout<<"主机IP地址:"<<endl; while(*pptr!=NULL) { cout<< inet_ntoa(*(struct in_addr *) (*pptr))<<endl; pptr++; } WSACleanup(); return 0; } 显示使用TCP服务的名称与端口号 #include "stdafx.h" #include "WinSock2.h" #include "iostream" #pragma comment(lib, "ws2_32.lib") using namespace std; int main(int argc, char **argv) { /***初始化WinSock DLL***/ WSADATA wsaData; WORD wVersionRequested =MAKEWORD(2,2); //生成版本号2.2 if(WSAStartup(wVersionRequested,&wsaData)!=0) { cout<<"加载WinSock DLL失败!\n"; return 0; } struct servent * pServer; for(int i=1;i<65535;i++) { // sptr = getservbyname("ftp", "tcp");//FTP using TCP pServer=getservbyport(htons(i), "TCP"); //获取服务信息 if(pServer!=NULL) { cout<<"服务名:"<<pServer->s_name<<endl; cout<<"协议:"<<pServer->s_proto<<endl; cout<<"端口号:"<<ntohs(pServer->s_port)<<endl; } } //注销WinSock DLL WSACleanup(); return 0; } 显示协议名称与协议号 #include "stdafx.h" #include "WinSock2.h" #include "iostream" #pragma comment(lib, "ws2_32.lib") using namespace std; int main(int argc, char **argv) { /***初始化WinSock DLL***/ WSADATA wsaData; WORD wVersionRequested =MAKEWORD(2,2); //生成版本号2.2 if(WSAStartup(wVersionRequested,&wsaData)!=0) { cout<<"加载WinSock DLL失败!\n"; return 0; } struct protoent *pProto; for(int i=1;i<=256;i++) { if((pProto=getprotobynumber(i))!=NULL) { cout<<"协议名:"<< pProto->p_name<<endl; cout<<"协议号:"<< pProto->p_proto <<endl; } } WSACleanup(); return 0; } TCP 流式套接字 字符传输+文件传输 Client #include "pch.h" #include <iostream> #include<WinSock2.h> #include <fstream> #define PORT 65432 #pragma warning(disable:4996) #pragma comment(lib, "ws2_32.lib") using namespace std; struct Student { char name[20]; int Eng; }; struct fileMessage { char fileName[256]; long int fileSize; }; void send_data(int sock_client) { char name[20]; int Eng; cin >> name; if (strcmp(name, "end") == 0) { struct Student stu; strcpy(stu.name, name); send(sock_client, (char *)&stu, sizeof(struct Student), 0); return; } cin >> Eng; struct Student stu; strcpy(stu.name, name); stu.Eng = Eng; stu.Eng = htonl(stu.Eng); send(sock_client, (char *)&stu, sizeof(struct Student), 0); cout << "信息发送完成!\n"; } void send_file(int sock_client) { char ok[3], filename[1000], file_buffer[1000]; struct fileMessage fileMsg; cout << "输入要传输的文件路径:"; cin>>filename; cout <<"D"<< filename << endl; int size = strlen(filename); while (filename[size] != '\\'&&size > 0) { size--; } strcpy(fileMsg.fileName, filename+size); ifstream inFile(filename, ios::in | ios::binary); if (!inFile.is_open()) { cout << "Cannot open " << filename << endl; return ; //文件打开失败则退出 } inFile.seekg(0, ios::end); size = inFile.tellg(); inFile.seekg(0, ios::beg); fileMsg.fileSize =htonl( size); send(sock_client, (char *)&fileMsg, sizeof(fileMsg), 0); if (recv(sock_client, ok, sizeof(ok), 0) <= 0) { cout << "接收OK失败,程序退出!\n"; return ; } if (strcmp(ok, "ok") == 0) { while (!inFile.eof()) { inFile.read(file_buffer, sizeof(file_buffer)); size = inFile.gcount(); send(sock_client, file_buffer, size, 0); } cout << "file transfer finished";//显示传输完成 inFile.close();//关闭文件 } else cout << "对方无法接收文件! "; } int main() { int sock_client; struct sockaddr_in server_addr; int addr_len = sizeof(struct sockaddr_in); char msg[256]; WSADATA wsaData; WORD wVersionRequested = MAKEWORD(2, 2); if (WSAStartup(wVersionRequested, &wsaData) != 0) { cout << "加载winsock.dll失败!\n"; return 0; } if ((sock_client = socket(AF_INET, SOCK_STREAM,0)) <0) { cout << "创建套接字失败,错误代码:" << WSAGetLastError() << endl; WSACleanup(); return 0; } char IP[100]; cout << "请输入服务器IP地址:" << endl; cin >> IP; memset((void *)&server_addr, 0, addr_len); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = inet_addr(IP); if (connect(sock_client, (struct sockaddr *)&server_addr, addr_len) != 0) { cout << "服务器连接失败,错误代码:" << WSAGetLastError() << endl; closesocket(sock_client); WSACleanup(); return 0; } int size; if ((size = recv(sock_client, msg, sizeof(msg), 0)) < 0) { cout << "失败,错误代码:" << WSAGetLastError() << endl; closesocket(sock_client); WSACleanup(); return 0; } else if (size == 0) { cout << "关闭连接,错误代码:" << WSAGetLastError() << endl; closesocket(sock_client); WSACleanup(); return 0; } else cout << msg << endl; while (1) { // send_data(sock_client); send_file(sock_client); } closesocket(sock_client); WSACleanup(); return 0; } Server #include "pch.h" #include <iostream> #include<fstream> #include<direct.h> #include <WinSock2.h> #define PORT 65432 #pragma warning(disable:4996) #pragma comment(lib, "ws2_32.lib") using namespace std; struct Student { char name[20]; int Eng; }; struct fileMessage { char fileName[256]; long int fileSize; }; void recv_file(SOCKET sock_client) { struct fileMessage fileMsg; long int filelen; char filename[1000] = "G:\\test\\"; char ok[3] = "ok"; char file_buffer[1000]; _mkdir(filename); if ((recv(sock_client, (char *)&fileMsg, sizeof(fileMsg),0)) <= 0) { cout << "未接收到文件名字及文件长度!\n"; return ; } filelen = ntohl(fileMsg.fileSize); strcat(filename, fileMsg.fileName); ofstream outFile(filename, ios::out | ios::binary); if(!outFile.is_open()) { cout << "Cannot open " << filename << endl; return; } send(sock_client, ok, sizeof(ok),0); int size = 0; do { size = recv(sock_client, file_buffer, sizeof(file_buffer), 0); outFile.write(file_buffer, size); filelen -= size; } while (size != 0 && filelen > 0); cout << "Transfer finished!\n"; outFile.close(); } void recv_data(SOCKET new_sock) { struct Student stu; if (recv(new_sock, (char *)&stu, sizeof(struct Student), 0) <= 0) { cout << "接收信息失败\n"; } else { if (strcmp(stu.name, "end") == 0) { cout << "通信结束\n"; return; } /*cout << client_addr.sin_port << " " << inet_ntoa(client_addr.sin_addr) << endl; struct sockaddr_in c_addr; int namelen; int n=getsockname(new_sock, (struct sockaddr *)&c_addr, &namelen); if (n == SOCKET_ERROR) { } else { cout << c_addr.sin_port << " " << inet_ntoa(c_addr.sin_addr) << endl; }*/ stu.Eng = ntohl(stu.Eng); cout << stu.name << " " << stu.Eng << endl; } } int main() { SOCKET sock_server; char msg[256]; char msg1[] = "成功连接服务器"; WSADATA wsaData; WORD wVersionRequests = MAKEWORD(2, 2); if (WSAStartup(wVersionRequests, &wsaData) != 0) { cout << "加载winsock.dll失败!\n"; return 0; } if ((sock_server = socket(AF_INET, SOCK_STREAM, 0)) < 0) { cout << "创建套接字失败!错误代码:" << WSAGetLastError() << endl; WSACleanup(); return 0; } int addr_len = sizeof(struct sockaddr_in); struct sockaddr_in addr; memset((void *)&addr, 0, sizeof(struct sockaddr)); addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sock_server, (struct sockaddr *)&addr, sizeof(addr)) != 0) { cout << "地址绑定失败!错误代码:" << WSAGetLastError() << endl; closesocket(sock_server); WSACleanup(); return 0; } if (listen(sock_server, 0) != 0) { cout << "listen函数调用失败!错误代码:" << WSAGetLastError() << endl; closesocket(sock_server); WSACleanup(); return 0; } else cout << "listenning......\n"; int size; struct sockaddr_in client_addr; SOCKET new_sock; if ((new_sock = accept(sock_server, (struct sockaddr *)&client_addr, &addr_len))== INVALID_SOCKET) { cout << "accept函数调用失败!错误代码:" << WSAGetLastError() << endl; closesocket(sock_server);//关闭监听套接字 WSACleanup();//注销WinSock动态链接库 return 0; } else { int size = send(new_sock, msg1, sizeof(msg1), 0); if (size < 0) { cout << "发送信息失败!错误代码:" << WSAGetLastError() << endl; closesocket(new_sock);//关闭已连接套接字 closesocket(sock_server);//关闭监听套接字 WSACleanup();//注销WinSock动态链接库 return 0; } else if (size == 0) { cout << "对方已关闭连接!\n"; closesocket(new_sock);//关闭已连接套接字 closesocket(sock_server);//关闭监听套接字 WSACleanup();//注销WinSock动态链接库 return 0; } else { cout << "信息发送成功!\n"; } cout << "收到的信息为:\n"; while (1) { //recv_data(new_sock); recv_file(new_sock); } closesocket(new_sock); } closesocket(sock_server);//关闭监听套接字 WSACleanup();//注销WinSock动态链接库 return 0; } TCP 流式套接字 多线程文件传输 Server(多连接客户发送) #include "stdafx.h" #include "iostream" #include "fstream" #include "process.h" //使用C++运行库中的函数创建多线程 #include "winsock2.h" #define PORT 65432 //定义服务器的监听端口号 #pragma comment(lib,"ws2_32.lib") using namespace std; char Command[20]="";//存放从键盘接收到的结束命令 char filename[128]; //存放从键盘输入的含有信息的文件名 char fname[128]; //存放发送给客户端的无路径信息的文件名 ifstream inFile; //定义文件输入流 unsigned int _stdcall GetCommand(void *par); //声明输入close命令的线程函数 unsigned int _stdcall SendFile(void *par); //声明发送文件的线程函数 int main() { /***定义相关的变量***/ int sock_server; struct sockaddr_in addr,client_addr; unsigned hThread1, hThread2; unsigned int ThreadID1,ThreadID2; int addr_len = sizeof(struct sockaddr_in); cout<<"请输入要发送的文件名:\n"; cin>>filename; /***以二进制读方式打开要分发的文件***/ inFile.open(filename, ios::in|ios::binary);//打开文件 if(!inFile.is_open()) { cout<<"Cannot open "<<filename<<endl; return 0; //文件打开失败则退出 } /***截取发送给客户端的文件名***/ int len=strlen(filename); int i=len; while(filename[i]!='\\' && i>=0)i--; if(i<0) i=0; else i++; int m=0; while(filename[m+i]!='\0') { fname[m]=filename[m+i]; m++; } /***初始化winsock DLL***/ WSADATA wsaData; WORD wVersionRequested=MAKEWORD(2,2); //生成版本号 if(WSAStartup(wVersionRequested,&wsaData)!=0) { cout<<"加载winsock.dll失败!\n"; return 0; } /***创建套接字***/ if ((sock_server = socket(AF_INET,SOCK_STREAM,0))<0) //建立一个socket { cout<<"创建套接字失败!\n"; WSACleanup(); return 0; } /***设置套接字为非阻塞模式***/ unsigned long ul =1; //设置套接字选项参数 int nRet = ioctlsocket(sock_server, FIONBIO, (unsigned long*)&ul); if (nRet == SOCKET_ERROR) { cout<<"设置套接字选项失败!\n"; closesocket(sock_server); WSACleanup(); return 0; } /***绑定IP端口***/ memset((void *)&addr,0,addr_len); addr.sin_family =AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY);//使用本机的所有IP地址 if(bind(sock_server,(LPSOCKADDR)&addr,sizeof(addr))!=0) { cout<<"绑定地址失败!\n"; closesocket(sock_server); WSACleanup(); return 0; } /***开始监听***/ if(listen(sock_server,5)!=0) { cout<<"listen函数调用失败!\n"; closesocket(sock_server); WSACleanup(); return 0; } else cout<<"listenning......\n"; /***启动命令接收线程***/ hThread1=_beginthreadex(NULL,0,GetCommand,(LPVOID)Command,0,&ThreadID1); /***接收并处理客户连接 ***/ SOCKET newsock; while(1) { Sleep(10); if(strcmp(Command,"close")==0)break ; //如果输入close命令则退出 newsock = accept(sock_server,(LPSOCKADDR)&client_addr,&addr_len); if(newsock!=INVALID_SOCKET) { cout<<"cnnect from "<<inet_ntoa(client_addr.sin_addr)<<endl; hThread2=_beginthreadex(NULL,0,SendFile,(LPVOID)newsock,0,&ThreadID2);//启动文件发送线程 } } inFile.close(); closesocket(sock_server); return 0; } /*****************文件传输线程函数********************************/ unsigned int _stdcall SendFile(void *par) { char buffer[1000]; inFile.seekg(0,ios::beg);//将文件读指针移动到文件头,如果少了本行,第二个客户收到的文件将是0字节 SOCKET sock=(SOCKET)par; /***设置套接字为阻塞模式***/ unsigned long ul =0; //设置套接字选项 int nRet = ioctlsocket(sock, FIONBIO, (unsigned long*)&ul); send(sock,(char*)fname,strlen(fname)+1,0); //发送文件名 int size=recv(sock,buffer,sizeof(buffer),0); //接收对方发来的“OK”消息 cout<<buffer<<endl; if(strcmp(buffer,"OK")!=0) { cout<<"客户端出错!\n"; closesocket(sock); //关闭socket return 0; } /****传输文件内容****/ while(!inFile.eof()) { inFile.read(buffer,sizeof(buffer)); size=inFile.gcount(); //获取实际读取的字节数 send(sock,(char*)buffer,size,0); } cout<<"文件传输结束!\n"; closesocket(sock); //关闭socket return 0; } /*************从键盘接收命令的线程函数********************/ unsigned int _stdcall GetCommand(void *par) { char * p=(char *)par; while(strcmp(p,"close")!=0) {Sleep(10);gets(p);} return 0; } TCP 流式套接字 I/O模型 Client Server #include "stdafx.h" #include "iostream" #include "winsock2.h" #define PORT 65432 //定义端口号常量 #define BUFFER_LEN 500 //定义接收缓冲区长度 #pragma comment(lib, "ws2_32.lib") using namespace std; int main(int argc, char **argv) { /***定义相关的变量***/ SOCKET sock_server,newsock; //定义监听套接字和临时已连接套接字变量 fd_set fdsock; //保存所有套接字的集合 fd_set fdread; //select要检测的可读套接字集合 struct sockaddr_in addr;//存放本地地址的sockaddr_in结构变量 struct sockaddr_in client_addr;//存放客户端地址的sockaddr_in结构变量 char msgbuffer[BUFFER_LEN];//定义用于接收客户端发来信息的缓区 char msg[] ="Connect succeed. Please send a message to me.\n"; //发给客户端的信息 /***初始化winsock2.DLL***/ WSADATA wsaData; WORD wVersionRequested=MAKEWORD(2,2); //生成版本号2.2 if(WSAStartup(wVersionRequested,&wsaData)!=0) { cout<<"加载winsock.dll失败!\n"; return 0; } /***创建套接字***/ if ((sock_server = socket(AF_INET,SOCK_STREAM,0))<0) { cout<<"创建套接字失败!\n"; WSACleanup(); return 0; } /***填写要绑定的本地地址***/ int addr_len = sizeof(struct sockaddr_in); memset((void *)&addr,0,addr_len); addr.sin_family =AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY);//允许套接字使用本机的任何IP /***给监听套接字绑定地址***/ if(bind(sock_server,( struct sockaddr *)&addr,sizeof(addr))!=0) { cout<<"地址绑定失败!\n"; closesocket(sock_server); WSACleanup(); return 0; } /***将套接字设为监听状态****/ if(listen(sock_server,0)!=0) { cout<<"listen函数调用失败!\n"; closesocket(sock_server); WSACleanup(); return 0; } else cout<<"listenning......\n"; FD_ZERO(&fdsock);//初始化fdsock FD_SET(sock_server, &fdsock);//将监听套接字加入到套接字集合fdsock /***循环:接收连接请求并收发数据***/ while(true) { FD_ZERO(&fdread);//初始化fdread fdread=fdsock;//将fdsock中的所有套接字添加到fdread中 if(select(0, &fdread, NULL, NULL, NULL)>0) { for(int i=0;i<fdsock.fd_count;i++) { if (FD_ISSET(fdsock.fd_array[i], &fdread)) { if(fdsock.fd_array[i]==sock_server) { //有客户连接请求到达,接收连接请求 newsock=accept (sock_server, (struct sockaddr *) &client_addr, &addr_len); if(newsock==INVALID_SOCKET) { //accept出错终止所有通信,结束程序 cout<<"accept函数调用失败!\n"; for(int j=0;j<fdsock.fd_count;j++) closesocket(fdsock.fd_array[j]); //关闭所有套接字 WSACleanup();//注销WinSock动态链接库 return 0; } else { cout<<inet_ntoa(client_addr.sin_addr)<<"连接成功!\n"; send(newsock,msg,sizeof(msg),0) ;//发送一段信息 FD_SET(newsock, &fdsock);//将新套接字加入fdsock } } else { //有客户发来数据,接收数据 memset((void *) msgbuffer,0, sizeof(msgbuffer));//缓冲区清零 int size=recv(fdsock.fd_array[i],msgbuffer,sizeof(msgbuffer),0); if(size<0) //接收信息 cout<<"接收信息失败!"<<endl; else if(size==0) cout<<"对方已关闭!\n"; else { //显示收到信息 getpeername(fdsock.fd_array[i], (struct sockaddr *)&client_addr, &addr_len); //获取对方IP地址 cout<< inet_ntoa(client_addr.sin_addr) <<":"<< msgbuffer << endl; } closesocket(fdsock.fd_array[i]); //关闭套接字 FD_CLR(fdsock.fd_array[i],&fdsock);//清除已关闭套接字 } } } } else { cout<<"Select调用失败!\n"; break;//终止循环退出程序 } } /***结束处理***/ for(int j=0;j<fdsock.fd_count; j++) closesocket (fdsock.fd_array[j]);//关闭所有已连接套接字 WSACleanup();//注销WinSock动态链接库 return 0; } UDP 数据报套接字 p2p和广播 多线程 #include "stdafx.h" #include "iostream" #include "winsock2.h" #define LOCALPORT 65431 //本端所用UDP端口号 #define PEERPORT 65432 //通信对端所用UDP端口号 #define PEERIP "127.0.0.1" //通信对端IP地址,调试程序时可使用环回地址 #define BUFFER_LEN 1000 #pragma comment(lib,"ws2_32.lib") using namespace std; struct sockaddr_in peeraddr,localaddr;//保存通信对端地址和本地地址的变量 int len =sizeof(struct sockaddr_in);//套接字函数中常用的地址长度 WSAEVENT bExit;//用于通知线程退出的事件对象句柄 /****************接收并显示信息的线程函数*****************/ DWORD WINAPI RecvMessage(LPVOID parsock) { SOCKET recvsock=(SOCKET)parsock; char recvBuffer[BUFFER_LEN]; int err; while(TRUE) { if(recvfrom(recvsock,recvBuffer,sizeof(recvBuffer),0,NULL,NULL)!=SOCKET_ERROR) //由于通信对端的地址已知,所以接收数据时可不必记录对方地址 { cout<< inet_ntoa(peeraddr.sin_addr)<<":"<<recvBuffer<<endl; if (strcmp(recvBuffer,"bye")==0) { //收到对方退出消息则结束本线程同时通知主线程 SetEvent(bExit); break; } } else { err=WSAGetLastError(); if(err==WSAECONNRESET){cout<<"The peer is closed!\n";continue;} cout<<"recive error:"<<err<<endl; SetEvent(bExit);break; } } return 0; } /****************输入并发送信息的线程函数*****************/ DWORD WINAPI SendMessage(LPVOID parsock) { SOCKET sendsock=(SOCKET)parsock; char sendBuffer[BUFFER_LEN]; while(true) { cout<<"Input the Message you want to send:"<<endl; cin.getline(sendBuffer,sizeof(sendBuffer)); sendto(sendsock,sendBuffer,strlen(sendBuffer)+1,0, (struct sockaddr*)& peeraddr,len); if (strcmp(sendBuffer,"bye")==0) {//如果输入的是bye,则本线程结束,同时通知主线程 SetEvent(bExit); break; } } return 0; } /****************程序主函数*****************/ int main(int argc, char* argv[]) { /***初始化winsock DLL***/ WSADATA wsaData; WORD wVersionRequested=MAKEWORD(2,2); //生成版本号2.2 if(WSAStartup(wVersionRequested,&wsaData)!=0) { cout<<"没有找到合适的winsock.dll!\n"; return 0; } /***创建事件对象***/ bExit=WSACreateEvent(); /***创建数据报套接字***/ SOCKET udpsocket; udpsocket=socket(AF_INET,SOCK_DGRAM,0); /***绑定本地地址***/ localaddr.sin_family=AF_INET; localaddr.sin_port=htons(LOCALPORT); //本端使用的UDP端口号 localaddr.sin_addr.s_addr= INADDR_ANY; //绑定本机所有IP地址 bind(udpsocket,(struct sockaddr*)&localaddr,len); /***指定通信对端地址***/ peeraddr.sin_family=AF_INET; peeraddr.sin_port=htons(PEERPORT); //指定对端使用的IP端口号 peeraddr.sin_addr.s_addr= inet_addr(PEERIP) ;//指定对端的IP地址 /***启动数据收发线程***/ HANDLE hThrdsnd,hThrdrcv; DWORD nThrdsnd,nThrdrcv; hThrdsnd=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SendMessage, (LPVOID)udpsocket,0,&nThrdsnd); hThrdrcv=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RecvMessage, (LPVOID)udpsocket,0,&nThrdrcv); /***等待线程的退出通知***/ WaitForSingleObject(bExit, INFINITE); /***结束处理***/ closesocket(udpsocket); WSACleanup(); return 0; } WSAAsyncSelect 初始代码 if ((m_DGramSocket1 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { CString str1("创建套接字失败"); MessageBox(str1); CDialogEx::OnOK(); } if ((m_DGramSocket2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { CString str1("创建套接字失败"); MessageBox(str1); CDialogEx::OnOK(); } memset((void *)&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(m_DGramSocket1, (LPSOCKADDR)&addr, sizeof(addr)) != 0) { MessageBox("绑定失败!"); closesocket(m_DGramSocket1); CDialogEx::OnOK(); } memset((void *)&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(PORT1); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(m_DGramSocket2, (LPSOCKADDR)&addr, sizeof(addr)) != 0) { MessageBox("绑定失败!"); closesocket(m_DGramSocket2); CDialogEx::OnOK(); } if (WSAAsyncSelect(m_DGramSocket1, m_hWnd, MsgRecv, FD_READ) != 0) { MessageBox("套接字异步事件注册失败!"); closesocket(m_DGramSocket1); } BOOL yes = TRUE; int vsize = sizeof(BOOL); setsockopt(m_DGramSocket2, SOL_SOCKET, SO_BROADCAST, (char *)&yes, vsize); if (WSAAsyncSelect(m_DGramSocket2, m_hWnd, MsgRecv, FD_READ) != 0) { MessageBox("套接字异步事件注册失败!"); closesocket(m_DGramSocket2); } 消息接受函数 char recvBuffer[1000]; CString str; int len = sizeof(fromaddr); int size = recvfrom(m_DGramSocket1, recvBuffer, sizeof(recvBuffer), 0, (sockaddr *)&fromaddr, &len); if (size > 0) { recvBuffer[size] = '\0'; str.Format("来自于%s:%d的消息:%s", inet_ntoa(fromaddr.sin_addr), ntohs(fromaddr.sin_port), recvBuffer); m_ListBox.AddString(str); } 单个发送 UpdateData(true); struct sockaddr_in toaddr; DWORD bwaddr; unsigned short mport; m_Ip.GetAddress(bwaddr); mport = atoi(m_Port.GetString()); memset((void *)&toaddr, 0, sizeof(addr)); toaddr.sin_family = AF_INET; toaddr.sin_addr.s_addr = htonl(bwaddr); toaddr.sin_port = htons(mport); m_ListBox.AddString("我说:" + m_Edit); sendto(m_DGramSocket1, m_Edit, m_Edit.GetLength(), 0, (sockaddr*)&toaddr, sizeof(toaddr)); 广播 // TODO: 在此添加控件通知处理程序代码 UpdateData(true); struct sockaddr_in toaddr; toaddr.sin_family = AF_INET; int mport = atoi(m_Port.GetString()); toaddr.sin_port = htons(mport); toaddr.sin_addr.S_un.S_addr = INADDR_BROADCAST; int a = sendto(m_DGramSocket2, m_Edit, m_Edit.GetLength(), 0, (sockaddr *)&toaddr, sizeof(toaddr)); m_ListBox.AddString("我说:" + m_Edit); 原始套接字 Ping #include "stdafx.h" #include <iostream> #include <winsock2.h> #pragma comment(lib, "WS2_32") #define DATALEN 1012 #define PACKAGENUM 10 //发送ICMP会从请求报文的个数 using namespace std; /***定义ICMP包结构***/ typedef struct icmp_hdr { unsigned char icmp_type; // ICMP包类型 unsigned char icmp_code; // 代码 unsigned short icmp_checksum; // 校验和 unsigned short icmp_id; // 惟一确定此请求的标识,通常设置为进程ID unsigned short icmp_sequence; // 序列号 unsigned long icmp_timestamp; // 时间戳 } IcmpHeader; unsigned short checksum(unsigned short* buff, int size); //校验和计算函数的声明 int main(int argc, char *argv[ ]) { /***加载Winsock2.2***/ WSADATA wsaData; int ret; if((ret=WSAStartup(MAKEWORD(1,0),&wsaData))!=0) { cout<<"初始化WinSock2.2出错!"; exit(0); } char szDestIp[256] ={0};//存放要Ping的IP地址或域名 //检查ping命令的使用格式是否正确,程序调试时可用后面的代码替换 /*if (argc < 2) { cout<<"\n用法: ping IP地址|域名\n"; return -1; } strcpy(szDestIp,argv[1]);*/ /***输入对方IP地址,调试程序时使用***/ cout<<"请输入你要Ping的IP地址...\n"; cin.getline(szDestIp,sizeof(szDestIp)); /***将点分十进制IP地址转换为32位二进制表示的IP地址***/ unsigned long ulDestIP= inet_addr(szDestIp); /****转换不成功时按域名解析****/ if(ulDestIP == INADDR_NONE) { hostent* pHostent = gethostbyname(szDestIp); if (pHostent!=NULL) ulDestIP = (*(in_addr*)pHostent->h_addr).s_addr; else //解析主机名失败 { cout<<"域名解析失败:"<<argv[1]<<"错误码:"<<WSAGetLastError()<<endl; WSACleanup(); return -1; } } /**** 创建收发ICMP包的原始套接字***/ SOCKET sRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); /***设置接收超时时间***/ int nTime=1000; ret = setsockopt(sRaw, SOL_SOCKET,SO_RCVTIMEO, (char*)&nTime, sizeof(nTime)); if(ret == SOCKET_ERROR) { cout<<"套接字选项设置出错!错误码:"<<WSAGetLastError()<<endl; return -1;; } /***设置ICMP包发送的目的地址***/ SOCKADDR_IN dest; dest.sin_family = AF_INET; dest.sin_port = htons(0); dest.sin_addr.S_un.S_addr = ulDestIP; /***创建ICMP包***/ char buff[sizeof(IcmpHeader) + DATALEN]; IcmpHeader* pIcmp = (IcmpHeader*)buff; /***填写ICMP包数据***/ pIcmp->icmp_type = 8; // ICMP回送请求 pIcmp->icmp_code = 0; pIcmp->icmp_id = (unsigned short)GetCurrentProcessId();//获取进程号作为ID pIcmp->icmp_timestamp = 0; //时间戳暂设置为0,具体值发送时再填 pIcmp->icmp_checksum = 0; //校验和在计算前应先设置为0 pIcmp->icmp_sequence = 0; //初始序列号 /***填充数据部分,可以为任意***/ memset(&buff[sizeof(IcmpHeader)], 'A', DATALEN); /***调用connect()函数为原始套接字指定通信对端地址***/ connect(sRaw,(SOCKADDR *)&dest, sizeof(dest)); /***收发ICMP报文***/ int n=0; bool bTimeout; unsigned short nSeq = 0;//发送的ICMP报文的序号 char recvBuf[32+DATALEN];//定义接收缓冲区 SOCKADDR_IN from; //保存收到的数据的源地址 int nLen = sizeof(from); //地址长度 IcmpHeader* pRecvIcmp; //指向ICMP报文首部的指针 while(TRUE) { static int nCount = 0; int nRet; if(nCount++ == PACKAGENUM) break; /***填写发送前才能填写的一些字段并发送ICMP包***/ pIcmp->icmp_checksum = 0; pIcmp->icmp_timestamp = GetTickCount();//时间戳 pIcmp->icmp_sequence = nSeq++; //包序号 pIcmp->icmp_checksum=checksum((unsigned short*)buff, sizeof(IcmpHeader)+DATALEN); nRet = send(sRaw, buff, sizeof(IcmpHeader) + DATALEN, 0); if(nRet == SOCKET_ERROR) { cout<<"发送失败!错误码:"<<WSAGetLastError()<<endl; closesocket(sRaw); WSACleanup(); return -1; } //接收对方返回的ICMP应答 bTimeout=FALSE; n=0; do{ n++;//接收预期ICMP应答报文的尝试次数加1 memset((void *)recvBuf,0,sizeof(recvBuf)); nRet = recvfrom(sRaw, recvBuf, sizeof(recvBuf), 0, (sockaddr*)&from, &nLen); if(nRet == SOCKET_ERROR) { if(WSAGetLastError() == WSAETIMEDOUT) { cout<<" timed out!\n"; bTimeout=TRUE; //接收时间超时 break; } cout<<"接收失败!错误码:"<<WSAGetLastError()<<endl; return -1; } pRecvIcmp = (IcmpHeader*)(recvBuf + 20); //收到的数据包含20个字节的IP首部,加20才是ICMP首部位置 if(pRecvIcmp->icmp_id != GetCurrentProcessId()) //收到报文是否为本程序发送的请求报文的应答报文 { //不是则重新接收 cout<<" 收到一个非预期的ICMP报文,忽略!\n"; } else //是则退出循环 break; }while(n<10);//重新接收次数不超过10则继续重试 if(n>10)// 收到太多非预期的ICMP报文则退出 { cout<<"对方机器向本机发送了太多的ICMP报文.\n"; closesocket(sRaw); WSACleanup(); return -1; } if(bTimeout)continue; //接收超时则发送下一个ICPM报文 /****解析接收到的ICMP包****/ int nTick = GetTickCount(); if(nRet < 20+ sizeof(IcmpHeader)) //收到的报文长度不足则不予解析 { cout<<"Too few bytes from"<<inet_ntoa(from.sin_addr)<<endl; continue; } else { //解析收到报文 cout<<nRet<<" bytes from :"<<inet_ntoa(from.sin_addr); cout <<" icmp_seq = "<<pRecvIcmp->icmp_sequence; cout<<" time:"<< nTick - pRecvIcmp->icmp_timestamp<<" ms \n"; Sleep(1000); //延时1秒再发送下一个数据包 } } closesocket(sRaw); WSACleanup(); return 0; } /*************计算校验和的函数***************/ unsigned short checksum(unsigned short* buff, int size) { unsigned long cksum = 0; while(size>1) { cksum += *buff++; size -= sizeof(unsigned short); } if(size)// 是奇数 cksum += *(char*)buff; //将32位的chsum高16位和低16位相加然后取反 cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); return (unsigned short)(~cksum); }
网络编程复习
猜你喜欢
转载自www.cnblogs.com/pxlsdz/p/12074088.html
今日推荐
周排行