socket接口在现代操作系统中得到了广泛的应用。Windows下的socket编程接口与Linux下的几乎一样。区别在于返回类型不同(句柄类型)。句柄不是文件描述符,也不是Windows中的一切(所以windows下socket不能用send和recv)Windows下socket()的用法SOCKETs={0};s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);//IPPROTO_TCP明确表示要创建TCP协议的socketwordif(s==INVALID){//创建socket时出错,returnINVALID_SOCKETERROR("...");return-1;}Windows网络编程接口#include函数原型函数说明SOCKETsocket(intaf,inttype,intprotocol);创建套接字,准备网络连接intconnect(SOCKETs,conststructsockaddr*addr,intlen);连接指定地址的远程设备intsend(SOCKETs,constchar*buf,intlen,intflags);发送数据到远程设备intrecv(SOCKETschar*buf,intlen,intflags);接收远程设备发回的数据intclosesocket(SOCKETs);关闭连接,销毁套接字intbind(SOCKETs,conststructsockaddr*addr,intlen);将套接字与指定地址相关联intlisten(SOCKETs,intbacklog);将套接字推入监听状态,等待连接SOCKETaccept(SOCKETs,structsockaddr*addr,intlen);接收客户端连接intshutdown(SOCKETs,inthowto);关闭连接,停止发送和接收closesandshutdown(同样在Linux下存在)区别:Shoutdown不释放socket资源一些细微差别通过WSAStartup()初始化系统环境(先调用)socket(),accept()错误返回INVALID_SOCKET(不能默认为-1)bind(),listen()错误返回SOCKET_ERROR(不能默认为-1)connect(),send(),recv()错误返回SOCKET_ERROR(不能默认为-1)通过WSACleanup()(最后调用)清除系统环境Windows网络编程专用说明在项目中设置链接ws2_32.lib属性中定义变量WSADATAwd选择套接字版本并初始化WSAStartup(MAKEWORD(2,2),&wd)Windows中有多个套接字版本MAKEWORD(1,2)//的主版本为1,次版本为2,return0x0201MAKEWORD(2,2)//主版本为2,次版本为2,返回0x0202编程实验:Windows网络编程实例client.c#include"stdafx.h"#includeint_tmain(intargc,_TCHAR*argv[]){SOCKETsock=0;//注意套接字类型structsockaddr_inaddr={0};intlen=0;字符buf[128]={0};字符输入[32]={0};整数r=0;WSADATAwd={0};//注意变量定义if(WSAStartup(MAKEWORD(2,2),&wd)!=0)//注意初始化系统环境{printf("startuperror\n");返回-1;}sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);如果(袜子==无效_SOCKET)//注意返回值类型{printf("socketerror\n");返回-1;}addr.sin_family=AF_INET;地址.sin_addr.s_addr=inet_addr("127.0.0.1");地址.sin_port=htons(8888);if(connect(sock,(structsockaddr*)&addr,sizeof(addr))==SOCKET_ERROR)//注意返回值类型{printf("connecterror\n");返回-1;}printf("连接成功\n");while(1){printf("输入:");scanf("%s",输入);len=send(sock,输入,strlen(输入)+1,0);r=recv(sock,buf,sizeof(buf),0);if(r>0){printf("接收:%s\n",buf);}else{休息;}}关闭套接字(袜子);//注意WSACleanup();//注意清除系统环境return0;}server.c//Server.cpp:定义控制台应用程序的入口点//#include"stdafx.h"#includeint_tmain(intargc,_TCHAR*argv[]){SOCKET服务器=0;结构sockaddr_insaddr={0};套接字客户端=0;结构sockaddr_incaddr={0};整数大小=0;int长度=0;字符buf[32]={0};整数r=0;WSADATAwd={0};if(WSAStartup(MAKEWORD(2,2),&wd)!=0){printf("启动错误\n");返回-1;}server=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);if(server==INVALID_SOCKET){printf("服务器套接字错误\n");返回-1;}saddr.sin_family=AF_INET;saddr.sin_addr.s_addr=htonl(INADDR_ANY);saddr.sin_port=htons(8888);if(bind(server,(structsockaddr*)&saddr,sizeof(saddr))==SOCKET_ERROR){printf("服务器绑定错误\n");返回-1;}if(listen(server,1)==SOCKET_ERROR){printf("服务器绑定错误\n");返回-1;}printf("服务器启动成功ess\n");while(1){asize=sizeof(caddr);client=accept(server,(structsockaddr*)&caddr,&asize);if(client==INVALID_SOCKET){printf("客户端接受错误\n");return-1;}printf("client:%d\n",client);do{r=recv(client,buf,sizeof(buf),0);if(r>0){printf("接收:%s\n",buf);if(strcmp(buf,"quit")!=0){len=send(client,buf,r,0);}else{break;}}}while(r>0);closesocket(client);}closesocket(server);WSACleanup();return0;}问题:select()是Linux系统独有的吗?Windows下的select()函数也提供了select()函数,参数与linux版本完全一致注意:windows下的select()函数,第一个参数没有任何含义(仅用于兼容性)#includeintselect(intnfds,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,conststructtimeval*timeout);一个细微差别:Windows中的select()是为Socket设计的fd_count用于记录感兴趣的套接字个数fd_array用于记录感兴趣的套接字句柄typedefstructfd_set{u_intfd_count;SOCKETfd_array[FD_SETSIZE];}fd_set;Windows中的select()函数使用示例temps=reads;timeout.tv_sec=0;timeout.tv_usec=10000;num=select(0,&temps,0,0,&timeout);if(num>0){unsignedinti=0;for(i=0;i0){buf[ret]=0;printf("接收:%s\n",buf);if(strcmp(buf,"quit")!=0){ret=send(client,buf,ret,0);}else{ret=-1;}}returnret;}int_tmain(intargc,_TCHAR*argv[]){SOCKET服务器=0;结构sockaddr_insaddr={0};//无符号整数最大值=0;整数=0;fd_set读取={0};fd_settemps={0};结构timeval超时={0};WSADATAwd={0};if(WSAStartup(MAKEWORD(2,2),&wd)!=0){printf("启动错误\n");返回-1;}server=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);如果(服务器==INVALID_SOCKET){printf("服务器套接字错误\n");返回-1;}saddr.sin_family=AF_INET;saddr.sin_addr.s_addr=htonl(INADDR_ANY);saddr.sin_port=htons(8888);if(bind(server,(structsockaddr*)&saddr,sizeof(saddr))==SOCKET_ERROR){printf("服务器绑定错误\n");返回-1;}if(listen(server,1)==SOCKET_ERROR){printf("serverlistenerror\n");返回-1;}printf("服务器启动成功\n");FD_ZERO(&读取);FD_SET(服务器,读取);//最大值=服务器;while(1){temps=读取;暂停。tv_sec=0;timeout.tv_usec=10000;//num=select(max+1,&temps,0,0,&timeout);num=select(0,&temps,0,0,&timeout);if(num>0){unsignedinti=0;for(i=0;i最大值)?客户:最大;printf("接受客户端:%d\n",客户端);}}else{intr=client_handler(sock);如果(r==-1){FD_CLR(sock,&reads);关闭套接字(袜子);}}}}}}关闭套接字(服务器);WSACleanup();return0;}思考:如何编写一个可以跨平台编译运行的网络程序?