Lesson10:网络编程基础
网络编程是计算机编程的一个重要分支,是网络通信的基础,网络编程主要用到了Windows系统系统提供的socket。网络通信又分为基于TCP和基于UDP两种。本文主要讲解基于TCP和UDP的网络编程基础知识。
#include <winsock2.h> #include <stdio.h> //#include <iostream> #pragma comment(lib,"ws2_32.lib") //静态加入一个lib文件,也就是库文件ws2_32.lib文件,它提供了对以下网络相关API的支持 void main() { /******** 首先设定通信版本 **************/ WORDwVersionRequested; WSADATAwsaData; interr; wVersionRequested= MAKEWORD(1, 1); //请求的通信版本为(1,1) err= WSAStartup(wVersionRequested, &wsaData); //调用WSAStartup函数 if(err != 0) return; //如果返回值不为0,表示没有对应的WinSockDLL.则返回 if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); //如果版本的高字节不为1,低字节不为1,则返回。 return; } //1创建套接字 SOCKETsockSrv = socket(AF_INET, SOCK_STREAM,0); //(1地址族AF_INET 或 PF_INET,2socket类型SOCK_STREAM或 SOCK_DGRAM,3与特定的地址家族相关的协议) 调用成功返回新的socket数据类型的套接字描述符 //2绑定套接字到本地地址和端口 /*structsockaddr_in{ short sin_family; //地址族 unsignedshort sin_port; //端口号 struct in_addr sin_addr; //套接字的主机IP地址 char sin_zero[8]; //填充数,使sockaddr_in和sockaddr结构长度一样 }*/ SOCKADDR_INaddrSrv; addrSrv.sin_addr.S_un.S_addr= htonl(INADDR_ANY); //调用htonl函数进行转换主机字节序为TCP/IP网络字节序//addrSrv是一个结构体,里面有一个结构体变量sin_addr,里面包含共用体S_un,然后是共用体成员S_addr,inet_addr函数进行主机字节序转换为网络字节序 addrSrv.sin_family= AF_INET; addrSrv.sin_port=htons(6000); //端口号为6000,需要1024以上端口号,网络字节序,需要转换,htonl和htons不同在于转换数据的范围 bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //绑定套接字和地址的 函数 (1指定要绑定的套接字,2该套接字的本地地址信息,是指向sockaddr结构的指针变量,3指定该地址的长度) //3调用listen函数,将套接字设置为监听模式,准备接受客户请求 listen(sockSrv,5); //(套接字描述符,最大的等待连接队列数) //4等待客户请求到来 //5用返回的套接字和客户端进行通信 //6返回,等待另一个客户请求 //7关闭套接字 SOCKADDR_INaddrClient; //定义一个地址结构的变量,用来接受客户端的地址信息,在循环结构中用到 intlen = sizeof(SOCKADDR); while(1) //死循环,一直监听,持续运行 { SOCKETsockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len); //(1处于监听状态的主机服务器套接字描述符,2指向buffer指针连接实体地址,保存了发起客户端的ip信息和端口信息,3指向整型指针,包含返回地址结构的长度),返回一个新的连接的套接字描述符,用他和客户端通信,先前的套接字继续监听客户连接请求 //发送数据 /*intsend( SOCKETs, //建立连接所对应的套接字描述符,不是监听的套接字 constchar FAR * buf, //一个buff指针,包含将要传送的数据 int len, //buffer中数据的长度 intflags //设定send的调用行为 );*/ charsendBuf[100]; sprintf_s(sendBuf,"Welcome%s to http://www.sunxin.org",inet_ntoa(addrClient.sin_addr)); //把格式化的数据写入某个字符串,将客户端地址传给字符串里的%s, send(sockConn,sendBuf, strlen(sendBuf)+1, 0); //接受数据 /*intrecv( The Windows Socketsrecv function receives data from a connected socket. SOCKETs, //建立连接的套接字 charFAR* buf, //接受数据的buff intlen, //buff的长度 intflags //设定接受函数的调用行为 );*/ charrecvBuf[100]; recv(sockConn,recvBuf, strlen(recvBuf) + 1, 0); printf("%s\n",recvBuf); closesocket(sockConn); } }
#include <winsock2.h> #include <stdio.h> //#include <iostream> #pragma comment(lib,"ws2_32.lib") void main() { /******** 首先设定通信版本 **************/ WORDwVersionRequested; WSADATAwsaData; interr; wVersionRequested= MAKEWORD(1, 1); //请求的通信版本为(1,1) err= WSAStartup(wVersionRequested, &wsaData); //调用WSAStartup函数 if(err != 0) return; //如果返回值不为0,表示没有对应的WinSockDLL.则返回 if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); //如果版本的高字节不为1,低字节不为1,则返回。 return; } //1创建套接字 SOCKETsockClient= socket(AF_INET, SOCK_STREAM, 0); //(1地址族AF_INET 或 PF_INET,2socket类型SOCK_STREAM或 SOCK_DGRAM,3与特定的地址家族相关的协议) 调用成功返回新的socket数据类型的套接字描述符 /*intconnect( //The Windows Socketsconnect function establishes a connection to a specifed socket. SOCKETs, //套接字 conststruct sockaddr FAR* name, //地址结构体指针,用来设定链接的服务器地址信息 intnamelen //地址结构体的长度 );*/ //2连接服务器 SOCKADDR_INaddrSrv; //SOCKADDR_IN是一个结构体变量 addrSrv.sin_addr.S_un.S_addr= inet_addr("127.0.0.1"); //addrSrv是一个结构体,里面有一个结构体变量sin_addr,里面包含共用体S_un,然后是共用体成员S_addr,inet_addr函数进行主机字节序转换为网络字节序 addrSrv.sin_family= AF_INET; addrSrv.sin_port= htons(6000); //主机字节序转换为网络字节序 connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //3和服务器端口进行通信(接受服务器发送的信息) charrecvBuf[100]; recv(sockClient,recvBuf, strlen(recvBuf) + 1, 0); printf("%s\n",recvBuf); send(sockClient,"This is zhangsan", strlen("This is zhangsan") + 1, 0); //4关闭套接字 closesocket(sockClient); WSACleanup(); //终止对套接字库的使用 system("pause"); //用于防止闪退 }
#include <winsock2.h> #include <stdio.h> #pragma comment(lib,"ws2_32.lib") void main() { /******** 首先设定通信版本 **************/ WORDwVersionRequested; WSADATAwsaData; interr; wVersionRequested= MAKEWORD(1, 1); //请求的通信版本为(1,1) err= WSAStartup(wVersionRequested, &wsaData); //调用WSAStartup函数 if(err != 0) return; //如果返回值不为0,表示没有对应的WinSockDLL.则返回 if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); //如果版本的高字节不为1,低字节不为1,则返回。 return; } //1创建套接字 SOCKETsockSrv = socket(AF_INET, SOCK_DGRAM, 0); //(1地址族AF_INET 或 PF_INET,2socket类型SOCK_STREAM或 SOCK_DGRAM,3与特定的地址家族相关的协议) 调用成功返回新的socket数据类型的套接字描述符 //2绑定套接字到本地地址和端口 SOCKADDR_INaddrSrv; addrSrv.sin_addr.S_un.S_addr= htonl(INADDR_ANY); //调用htonl函数进行转换主机字节序为TCP/IP网络字节序 addrSrv.sin_family= AF_INET; addrSrv.sin_port= htons(6000); //端口号为6000,1024以上端口号,需要网络字节序,需要转换,htonl和htons不同在于转换数据的范围 bind(sockSrv,(SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); //绑定函数 (1指定要绑定的套接字,2该套接字的本地地址信息,是指向sockaddr结构的指针变量,3指定该地址的长度) /*intrecvfrom( The Windows Socketsrecvfrom function receives a datagram and stores the source address. SOCKETs, //套接字 charFAR* buf, //接收数据的buffer int len, //buffer的长度 int flags, //设定recvfrom函数的调用行为 structsockaddr FAR* from, //地址结构体指针,接收发送数据方的地址信息 intFAR* fromlen //函数返回值,返回地址结构的大小 );*/ //3等待接收数据recvfrom SOCKADDR_INaddrClient; //定义一个地址结构的变量,用来接受客户端的地址信息,在循环结构中用到 intlen = sizeof(SOCKADDR); charrecvBuf[100]; recvfrom(sockSrv,recvBuf, strlen(recvBuf) + 1, 0, (SOCKADDR*)&addrClient, &len); printf("%s\n",recvBuf); //4关闭套接字 closesocket(sockSrv); WSACleanup(); //终止对套接字库的使用 system("pause"); //用于防止闪退 }
#include <winsock2.h> #include <stdio.h> #pragma comment(lib,"ws2_32.lib") void main() { /******** 首先设定通信版本 **************/ WORDwVersionRequested; WSADATAwsaData; interr; wVersionRequested= MAKEWORD(1, 1); //请求的通信版本为(1,1) err= WSAStartup(wVersionRequested, &wsaData); //调用WSAStartup函数 if(err != 0) return; //如果返回值不为0,表示没有对应的WinSockDLL.则返回 if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); //如果版本的高字节不为1,低字节不为1,则返回。 return; } //1创建套接字 SOCKETsockClient = socket(AF_INET, SOCK_DGRAM, 0); //(1地址族AF_INET 或 PF_INET,2socket类型SOCK_STREAM或 SOCK_DGRAM,3与特定的地址家族相关的协议) 调用成功返回新的socket数据类型的套接字描述符 /*intsendto( The Windows Sockets sendtofunction sends data to a specific destination. SOCKETs, //套接字 constchar FAR * buf, //包含将要发送的数据 int len, //数据的长度 intflags, //设置sendto函数调用行为 conststruct sockaddr FAR * to, //地址结构体指针,设定目的套接字的地址信息 inttolen //地址结构体的长度 );*/ //2向服务器发送数据(sendto) SOCKADDR_INaddrSrv; addrSrv.sin_addr.S_un.S_addr= inet_addr("127.0.0.1"); addrSrv.sin_family= AF_INET; addrSrv.sin_port= htons(6000); sendto(sockClient,"Hello", strlen("Hello") + 1, 0, (SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //3关闭套接字 closesocket(sockClient); WSACleanup(); //终止对套接字库的使用 system("pause"); //用于防止闪退 }