您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > C++多线程通信例子
关于winsock服务器和客户端编程2008年12月28日星期日23:22在网络编程中,最常用和最基础的就是WINSOCK.现在我们讨论WINDOWS下的SOCKET编程.大凡在WIN32平台上的WINSOCK编程都要经过下列步骤:定义变量-获得WINDOCK版本-加载WINSOCK库-初始化-创建套接字-设置套接字选项-关闭套接字-卸载WINSOCK库-释放资源下面介绍WINSOCKC/S的建立过程:服务器客户端________________________________________________1初始化WSA1初始化WSA____________________________________________________2建立一个SOCKET2建立一个SOCKET_____________________________________________________3绑定SOCKET3连接到服务器_____________________________________________________4在指定的端口监听4发送和接受数据_____________________________________________________5接受一个连接5断开连接______________________________________________________-6发送和接受数据___________________________________________________7断开连接__________________________________________________大家注意,在VC中进行WINSOCK编程时,需要引入如下两个库文件:WINSOCK.H(这个是WINSOCKAPI的头文件,WIN2K以上支持WINSOCK2,所以可以用WINSOCK2.H);Ws2_32.lib(WINSOCKAPI连接库文件).使用方式如下:#includewinsock.h#pragmacomment(lib,ws2_32.lib)下面我们通过具体的代码演示服务器和客户端的工作流程:首先,建立一个WSADATA结构,通常用wsaDataWSADATAwsaData;然后,调用WSAStartup函数,这个函数是连接应用程序与winsock.dll的第一个调用.其中,第一个参数是WINSOCK版本号,第二个参数是指向WSADATA的指针.该函数返回一个INT型值,通过检查这个值来确定初始化是否成功.调用格式如下:WSAStartup(MAKEWORD(2,2),&wsaData),其中MAKEWORD(2,2)表示使用WINSOCK2版本.wsaData用来存储系统传回的关于WINSOCK的资料.if(iResuit=WSAStartup(MAKEWORD(2,2),&wsaData)!=0){printf(WSAStartupfailed:%d,GetLastError());//返回值不等与0,说明初始化失败ExitProcess();//退出程序}应用程序在完成对请求的SOCKET库使用后,要调用WSACleanup函数来接触SOCKET库的绑定,并且释放资源.注意WSAStartup初始化后,必须建立一个SOCKET结构来保存SOCKET句柄.下面我们建立一个SOCKET.首先我们建立一个m_socket的SOCKET句柄,接着调用socket()函数,函数返回值保存在m_socket中.我们使用AF_INFE,SOCK_STREAM,IPPROTO_TCP三个参数.第一个表示地址族,AF_INFE表示TCP/IP族,第二个表示服务类型,在WINSOCK2中,SOCKET支持以下三种类型;SOCK_STREAM流式套接字SOCK_DGRAM数据报套接字SOCK_RAW原始套接字第三个参数表示协议:IPPROTO_UDPUDP协议用于无连接数据报套接字IPPROTO_TCPTCP协议用于流式套接字IPPROTO_ICMPICMP协议用于原始套接字m_socket=socket(AF_INFE,SOCK_STREAM,IPPROTO_TCP);//创建TCP协议以下代码用于检查返回值是否有错误:if(m_scoket==INVALID_SOCKET){prinrf(Erroratsocket():%d\n,GetLastError());WSACleanup();//释放资源return;}说明,如果socket()调用失败,他将返回INVALID_SOCKET.为了服务器能接受一个连接,他必须绑定一个网络地址,下面的代码展示如何绑定一个已经初始化的IP和端口的Socket.客户端程序用这个IP地址和端口来连接服务器.sockaddr_inservice;service.sin_family=AF_INET;//INTERNET地址族service.sin_addr.s_addr=inet_addr(127.0.0.1);//将要绑定的本地IP地址service.sin_port=htons(27015);//27015将要绑定的端口下面我们调用BIND函数,把SOCKET和SOCKADDR以参数的形式传入,并检查错误.if(bind(m_socket,(SOCKADDR*)&SERVICE,sizeof(service))==SOCKET_ERROR){printf(bind()failed.\n);closesocket(m_socket);return;}当绑定完成后,服务器必须建立一个监听队列,以接受客户端的请求.listen()使服务器进入监听状态,该函数调用成功返回0,否则返回SOCKET_ERROR.代码如下:if(listen(m_socket,1)==SOCKET-ERROR){printf(errorlisteningonsocket.\n);}服务器端调用完LISTEN()后,如果此时客户端调用CONNECT()函数,服务器端必须在调用ACCEPT().这样服务器和客户端才算正式完成通信程序的连接动作.一旦服务器开始监听,我们就要指定一个句柄来表示利用ACCEPT()函数接受的连接,这个句柄是用来发送和接受数据的表示.建立一个SOCKET句柄SocketAcceptSocket然后利用无限循环来检测是否有连接传入.一但有连接请求,ACCEPT()函数就会被调用,并且返回这次连接的句柄.printf(waitongforaclienttoconnect...\n);while(1){AcceptSocket=SOCKET_ERROR;while(AcceptSocket==SOCKET_ERROR){AcceptSocket=accept(m_socket,NULL,NULL);}}下面看客户端端代码:sockaddr_inclientService;clientService.sin_family=AF_INET;//INTERNET地址族clientService.sin_addr.s_addr=inet_addr(127.0.0.1);//将要绑定的本地IP地址clientService.sin_port=htons(27015);//27015将要绑定的端口下面调用CONNECT()函数:if(connect(m_socket,(SOCKADDR*)&clientService,sizeof(clientService))==SOCKET_ERROR){printf(Failedtoconnect.\n);WSACleanup();return;}//如果调用失败清理退出//调用成功继续读写数据_________________________________________________________________________________________________到这里,服务器和客户端的基本流程介绍完毕,下面我们介绍数据交换.send():intsend{SOCKETs,//指定发送端套接字constcharFAR?*buf,//指明一个存放应用程序要发送的数据的缓冲区intlen,//实际要发送的数据字节数intflags//一般设置为0};C/S都用SEND函数向TCP连接的另一端发送数据.recv():intrecv{SOCKETs,//指定发送端套接字charFAR?*buf,//指明一个缓冲区存放RECC受到的数据intlen,//指明BUF的长度intflags//一般设置为0};C/S都使用RECV函数从TCP连接的另一端接受数据下面将完整的程序代码提供如下,大家可直接编译运行首先看客户端的代码:#includestdio.h#includewinsock2.h#pragmacomment(lib,ws2_32.lib)voidmain(){//初始化Winsock.WSADATAwsaData;intiResult=WSAStartup(MAKEWORD(2,2),&wsaData);if(iResult!=NO_ERROR)printf(ErroratWSAStartup()\n);//建立socketsocket.SOCKETclient;client=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(client==INVALID_SOCKET){printf(Erroratsocket():%ld\n,WSAGetLastError());WSACleanup();return;}//连接到服务器.sockaddr_inclientService;clientService.sin_family=AF_INET;clientService.sin_addr.s_addr=inet_addr(127.0.0.1);clientService.sin_port=htons(27015);if(connect(client,(SOCKADDR*)&clientService,sizeof(clientService))==SOCKET_ERROR){printf(Failedtoconnect.\n);WSACleanup();return;}//发送并接收数据.intbytesSent;intbytesRecv=SOCKET_ERROR;charsendbuf[32]=Client:Sendingdata.;charrecvbuf[32]=;bytesSent=send(client,sendbuf,strlen(sendbuf),0);printf(BytesSent:%ld\n,bytesSent);while(bytesRecv==SOCKET_ERROR){bytesRecv=recv(client,recvbuf,32,0);if(bytesRecv==0||bytesRecv==WSAECONNRESET){printf(ConnectionClosed.\n);break;}if(bytesRecv0)return;printf(BytesRecv:%ld\n,bytesRecv);}return;}下面是服务器端代码:#includestdio.h#includewinsock2.h#pragmacomment(lib,ws2_32.lib)voidmain(){//初始化WSADATAwsaData;intiResult=WSAStartup(MAKEWORD(2,2),&wsaData);if(iResult!=NO_ERROR)printf(ErroratWSAStartup()\n);//建立socketSOCKETserver;server=socket(AF_INET,SOCK_STREAM,IPPROTO
本文标题:C++多线程通信例子
链接地址:https://www.777doc.com/doc-309282 .html