WinSock的同步异步、阻塞非阻塞问题

yuhaouestc 2017-06-27 03:38:13
用了别人写得程序,但是没搞懂。。。
用的select模型,是不是就是同步的方式,那阻塞和非阻塞有是怎么判断的呢

Init里面就是连接和接收数据

TcpInit()
{
if (!m_bClientConnected)
{
int m_nPortRemote = 5025;
CString m_strRemoteIP = _T("192.168.1.58");
DWORD IP = inet_addr((LPCTSTR)m_strRemoteIP);
if(!m_pSockClient->Connect(m_strRemoteIP,m_nPortRemote))
{
int a=0;
return;
}
if(!m_pSockClient->StartReceiving(TcpStatusChangeCallBack,TcpRecvCallBack,(DWORD)this))
{
int a=0;
m_pSockClient->Close();
return;
}
m_bClientConnected=TRUE;
}
WriteCmd("FORMat:DATA INT,16\n",20);
}

接收数据里面开启了一个线程,并且有两个回调函数,一个状态一个数据

StartReceiving(LPStatusProc proc1,LPDataArriveProc proc2,DWORD userdata)
{
if(!m_bAvailable)
{
return FALSE;
}
if(m_nType==TCP_SOCKET_SERVER)
{
return FALSE;
}
if(!m_bCreated)
{
return FALSE;
}
if(m_bAuto)
{
return FALSE;
}

//开始自动接收
m_lpClientStatusProc=proc1;
m_lpClientDataArriveProc=proc2;
m_dwUserData=userdata;
m_bAuto=TRUE;

DWORD dwThreadId;

m_hServerThread=CreateThread(NULL,0,ClientThread,this,0,&dwThreadId);

if(m_hServerThread==NULL)
{
m_bAuto=FALSE;
error=WSAGetLastError();
return FALSE;
}

return TRUE;
}

客户端线程
ClientThread(LPVOID lpParameter)
{
CTCPSocket* m_pTCP=(CTCPSocket*)lpParameter;

int nRet;
char buf[256];

timeval tv={0,5000};
fd_set fs;

//不断接收服务器发来数据
while(m_pTCP->m_bAuto)
{
FD_ZERO(&fs);
FD_SET(m_pTCP->m_sSocket,&fs);
if(select(1,&fs,NULL,NULL,&tv)==1)
{
nRet=recv(m_pTCP->m_sSocket,buf,256,0);

if(nRet==SOCKET_ERROR)
{
//出错断开(例如服务器关闭)
m_pTCP->error=WSAGetLastError();
closesocket(m_pTCP->m_sSocket);
m_pTCP->m_bAuto=FALSE;
TRACE("客户端出错断开! \n");

//回调处理
if(m_pTCP->m_lpClientStatusProc!=NULL)
{
char* inf;
inf=new char[22];
inf[0]='C';
inf[1]='D';
m_pTCP->m_lpClientStatusProc(inf,22,m_pTCP->m_dwUserData);
delete inf;
}

break;
}

if(nRet>0)
{
//收到新的数据
//TRACE("客户端收到数据%d字节! \n",nRet);

//数据回调处理
if(m_pTCP->m_lpClientDataArriveProc!=NULL)
{
char* inf;
inf=new char[nRet];
memcpy(inf,buf,nRet);
m_pTCP->m_lpClientDataArriveProc(inf,nRet,m_pTCP->m_dwUserData);
delete inf;
}

continue;
}

if(nRet==0)
{
//服务器正常断开
TRACE("客户端正常断开! \n");

//回调处理
if(m_pTCP->m_lpClientStatusProc!=NULL)
{
char* inf;
inf=new char[22];
inf[0]='C';
inf[1]='D';
m_pTCP->m_lpClientStatusProc(inf,22,m_pTCP->m_dwUserData);
delete inf;
}
closesocket(m_pTCP->m_sSocket);
m_pTCP->m_bAuto=FALSE;

break;
}
}
}

return 0;
}
...全文
306 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2017-06-29
  • 打赏
  • 举报
回复
赵4老师 2017-06-29
  • 打赏
  • 举报
回复
用事实说话,焦点访谈; 用代码说话,真程序员。
赵4老师 2017-06-28
  • 打赏
  • 举报
回复
MSDN98_1\SAMPLES\VC98\SDK\NETDS\WINSOCK\SIMPLE\IOCTL.C
/******************************************************************************\
* ioctl.c - TCP server
*
*       This is a part of the Microsoft Source Code Samples.
*       Copyright 1996-1997 Microsoft Corporation.
*       All rights reserved.
*       This source code is only intended as a supplement to
*       Microsoft Development Tools and/or WinHelp documentation.
*       See these sources for detailed information regarding the
*       Microsoft samples programs.
\******************************************************************************/



#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DEFAULT_PORT 5001

int ReadAndEcho(SOCKET , char *,int ) ;
int WriteMessage(SOCKET , char *,int ) ;

void Usage(char *progname) {
	fprintf(stderr,"Usage\n%s -e [endpoint] -i [interface]\n",
		progname);
	fprintf(stderr,"Where:\n");
	fprintf(stderr,"\tendpoint is the port to listen on\n");
	fprintf(stderr,"\tinterface is the ipaddr (in dotted decimal notation)");
	fprintf(stderr," to bind to\n");
	fprintf(stderr,"Defaults are 5001 and INADDR_ANY\n");
	WSACleanup();
	exit(1);
}
int main(int argc, char **argv) {

	char Buffer[128];
	char *interface= NULL;
	unsigned short port=DEFAULT_PORT;
	int	fromlen;
	int	i, ioctl_opt =1;
	struct sockaddr_in local, from;
	WSADATA	wsaData;
	SOCKET listen_socket, msgsock;
	fd_set readfds,	writefds, exceptfds;

	/* Parse arguments */
	if (argc >1) {
		for(i=1;i <argc;i++) {
			if ( (argv[i][0] ==	'-') || (argv[i][0] == '/') ) {
				switch(tolower(argv[i][1]))	{
					case 'i':
						interface =	argv[++i];
						break;
					case 'e':
						port = atoi(argv[++i]);
						break;
					default:
						Usage(argv[0]);
						break;
				}
			}
			else
				Usage(argv[0]);
		}
	}
 
	if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR)	{
		fprintf(stderr,"WSAStartup failed with error %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}
 
	if (port ==	0){
		Usage(argv[0]);
	}

	//
	// The fd sets should be zeroed	out	before using them to prevent errors.
	FD_ZERO(&readfds);
	FD_ZERO(&writefds);
	FD_ZERO(&exceptfds);
	memset(Buffer,0,sizeof(Buffer));

	local.sin_family = AF_INET;

	//
	// bind	to specific	interface if desired.

	local.sin_addr.s_addr =	(!interface)?INADDR_ANY:inet_addr(interface);

	/*
	 * Port	MUST be	in Network Byte	Order
	 */
	local.sin_port = htons(port);

	listen_socket =	socket(AF_INET,	SOCK_STREAM,0);	// TCP socket
	if (listen_socket == INVALID_SOCKET){
		fprintf(stderr,"socket() failed with error %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}
	//
	// bind() associates a local address and port combination with the
	// socket just created.

	if (bind(listen_socket,(struct sockaddr*)&local,sizeof(local) )
		== SOCKET_ERROR) {
		fprintf(stderr,"bind() failed with error %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}

	//
	// start listening on the socket for incoming connections
	//
	if (listen(listen_socket,5)	== SOCKET_ERROR) {
		fprintf(stderr,"listen() failed with error %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}
	printf("%s: Listening on port %d\n",argv[0],port);

	//
	// Set the socket to non-blocking mode.
	//
	if (ioctlsocket(listen_socket,FIONBIO,&ioctl_opt) == SOCKET_ERROR) {
		fprintf(stderr,"ioctlsocket failed %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}
	//
	// The structure of	the	loop below is very simple. We only accept one
	// connection at a time. As	soon as	another	client connects, we
	// disconnect the first	one, and start talking to the new client.
	// All this	server does	is to echo the data	received on	the	socket
	// back	to the client.
	//
	// This	is not a very realistic	server,	but	it does	serve to show that
	// select()	does not scale very	well on	win32. If we were dealing
	// with	more than one client, we would have	to have	a list of sockets
	// that	are	in each	fdset to be	able to	check them when	select()
	// returns.
	//
	while(1) {

		//
		// A socket	in the listen()	state becomes ready	to read	when a
		// client connects to it. An accept() will complete	without
		// blocking.
		// Since select	sets the sockets that are ready	to be read from	or
		// written to, we have to include listen_socket	in the fdset each time
		// through the loop.
		//

		FD_SET(listen_socket,&readfds);

		i =	select(0,&readfds,&writefds,&exceptfds,NULL);
		if (i == SOCKET_ERROR) {
			fprintf(stderr,"select failed %d\n",WSAGetLastError());
		}
		if (i==0){
			fprintf(stderr,"Select returned no fds ready\n");
		}

		if (FD_ISSET(listen_socket,	&readfds)){
			//
			// close the previous client socket.
			// We must also	clear it from the fdset	to prevent select()
			// from	failing.
			//
			closesocket(msgsock);
			FD_CLR(msgsock,&readfds);
			FD_CLR(msgsock,&writefds);
			fromlen	= sizeof(from);
			msgsock= accept(listen_socket,(struct sockaddr*)&from,&fromlen);
			if (msgsock == INVALID_SOCKET) {
				fprintf(stderr,"accept failed %d\n",WSAGetLastError());
				WSACleanup();
				return -1;
			}
			FD_SET(msgsock,&writefds);
			FD_SET(msgsock,&readfds);
			continue;
		}
		if (FD_ISSET(msgsock,&readfds) ) {
			//
			// socket is ready to read, i.e., there is data on the socket.
			//
			if (ReadAndEcho(msgsock,Buffer,sizeof(Buffer))<0) {
				fprintf(stderr,"terminating connection\n");
				FD_CLR(msgsock,&readfds);
				FD_CLR(msgsock,&writefds);
				closesocket(msgsock);
				continue;
			}
		}
		if (FD_ISSET(msgsock,&writefds) ){
			if (WriteMessage(msgsock,Buffer,sizeof(Buffer)) <=0) {
				fprintf(stderr,"terminating connection\n");
				FD_CLR(msgsock,&readfds);
				FD_CLR(msgsock,&writefds);
				closesocket(msgsock);
				continue;
			}
		}
		FD_SET(msgsock,&writefds);
		FD_SET(msgsock,&readfds);
	}
}
int ReadAndEcho(SOCKET insock, char *Buffer,int size) {
	int rc;

	rc = recv(insock,Buffer,size,0);

	if (rc == SOCKET_ERROR) {
		fprintf(stderr,"recv() failed with error %d\n",WSAGetLastError());	
		return -1;
	}
	if (rc ==0) {
		fprintf(stderr,"Connection closed by client\n");
		return 0;
	}
	printf("Received [%s] from client\n",Buffer);
	return rc;
}
int WriteMessage(SOCKET outsock, char *Buffer,int size) {
	int rc;
	int lasterr;

	printf("Sending [%s] to client\n",Buffer);
	rc = send(outsock,Buffer,size, 0);

	if (rc == SOCKET_ERROR) {
	  lasterr = WSAGetLastError();
	  if (lasterr == WSAEWOULDBLOCK)
		return 0;
	  else {
		fprintf(stderr,"send() failed with error %d\n",lasterr);	
		return -1;
	  }
	}
	if (rc ==0) {
		fprintf(stderr,"Connection closed by client\n");
	}
	return rc;
}
赵4老师 2017-06-28
  • 打赏
  • 举报
回复
MSDN98_1\SAMPLES\VC98\SDK\NETDS\WINSOCK\SIMPLE\SIMPLES.C
/******************************************************************************\
* simples.c - Simple TCP/UDP server using Winsock 1.1
*       This is a part of the Microsoft Source Code Samples.
*       Copyright 1996-1997 Microsoft Corporation.
*       All rights reserved.
*       This source code is only intended as a supplement to
*       Microsoft Development Tools and/or WinHelp documentation.
*       See these sources for detailed information regarding the
*       Microsoft samples programs.
\******************************************************************************/

#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DEFAULT_PORT 5001
#define DEFAULT_PROTO SOCK_STREAM // TCP

void Usage(char *progname) {
	fprintf(stderr,"Usage\n%s -p [protocol] -e [endpoint] -i [interface]\n",
		progname);
	fprintf(stderr,"Where:\n\tprotocol is one of TCP or UDP\n");
	fprintf(stderr,"\tendpoint is the port to listen on\n");
	fprintf(stderr,"\tinterface is the ipaddr (in dotted decimal notation)");
	fprintf(stderr," to bind to\n");
	fprintf(stderr,"Defaults are TCP,5001 and INADDR_ANY\n");
	WSACleanup();
	exit(1);
}
int main(int argc, char **argv) {

	char Buffer[128];
	char *interface= NULL;
	unsigned short port=DEFAULT_PORT;
	int	retval;
	int	fromlen;
	int	i;
	int	socket_type	= DEFAULT_PROTO;
	struct sockaddr_in local, from;
	WSADATA	wsaData;
	SOCKET listen_socket, msgsock;

	/* Parse arguments */
	if (argc >1) {
		for(i=1;i <argc;i++) {
			if ( (argv[i][0] ==	'-') || (argv[i][0] == '/') ) {
				switch(tolower(argv[i][1]))	{
					case 'p':
						if (!stricmp(argv[i+1],	"TCP") )
							socket_type	= SOCK_STREAM;
						else if	(!stricmp(argv[i+1], "UDP") )
							socket_type	= SOCK_DGRAM;
						else
							Usage(argv[0]);
						i++;
						break;

					case 'i':
						interface = argv[++i];
						break;
					case 'e':
						port = atoi(argv[++i]);
						break;
					default:
						Usage(argv[0]);
						break;
				}
			}
			else
				Usage(argv[0]);
		}
	}
	
	if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) {
		fprintf(stderr,"WSAStartup failed with error %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}
	
	if (port == 0){
		Usage(argv[0]);
	}

	local.sin_family = AF_INET;
	local.sin_addr.s_addr = (!interface)?INADDR_ANY:inet_addr(interface);

	/*
	 * Port MUST be in Network Byte Order
	 */
	local.sin_port = htons(port);

	listen_socket = socket(AF_INET, socket_type,0); // TCP socket
	
	if (listen_socket == INVALID_SOCKET){
		fprintf(stderr,"socket() failed with error %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}
	//
	// bind() associates a local address and port combination with the
	// socket just created. This is most useful when the application is a
	// server that has a well-known port that clients know about in advance.
	//

	if (bind(listen_socket,(struct sockaddr*)&local,sizeof(local) )
		== SOCKET_ERROR) {
		fprintf(stderr,"bind() failed with error %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}

	//
	// So far, everything we did was applicable to TCP as well as UDP.
	// However, there are certain steps that do not work when the server is
	// using UDP.
	//

	// We cannot listen() on a UDP socket.

	if (socket_type != SOCK_DGRAM) {
		if (listen(listen_socket,5) == SOCKET_ERROR) {
			fprintf(stderr,"listen() failed with error %d\n",WSAGetLastError());
			WSACleanup();
			return -1;
		}
	}
	printf("%s: 'Listening' on port %d, protocol %s\n",argv[0],port,
		(socket_type == SOCK_STREAM)?"TCP":"UDP");
	while(1) {
		fromlen =sizeof(from);
		//
		// accept() doesn't make sense on UDP, since we do not listen()
		//
		if (socket_type != SOCK_DGRAM) {
			msgsock = accept(listen_socket,(struct sockaddr*)&from, &fromlen);
			if (msgsock == INVALID_SOCKET) {
				fprintf(stderr,"accept() error %d\n",WSAGetLastError());
				WSACleanup();
				return -1;
			}
			printf("accepted connection from %s, port %d\n",
						inet_ntoa(from.sin_addr),
						htons(from.sin_port)) ;
			
		}
		else
			msgsock = listen_socket;

		//
		// In the case of SOCK_STREAM, the server can do recv() and
		// send() on the accepted socket and then close it.

		// However, for SOCK_DGRAM (UDP), the server will do
		// recvfrom() and sendto()  in a loop.

		if (socket_type != SOCK_DGRAM)
			retval = recv(msgsock,Buffer,sizeof (Buffer),0 );
		else {
			retval = recvfrom(msgsock,Buffer,sizeof (Buffer),0,
				(struct sockaddr *)&from,&fromlen);
			printf("Received datagram from %s\n",inet_ntoa(from.sin_addr));
		}
			
		if (retval == SOCKET_ERROR) {
			fprintf(stderr,"recv() failed: error %d\n",WSAGetLastError());
			closesocket(msgsock);
			continue;
		}
		if (retval == 0) {
			printf("Client closed connection\n");
			closesocket(msgsock);
			continue;
		}
		printf("Received %d bytes, data [%s] from client\n",retval,Buffer);

		printf("Echoing same data back to client\n");
		if (socket_type != SOCK_DGRAM)
			retval = send(msgsock,Buffer,sizeof(Buffer),0);
		else
			retval = sendto(msgsock,Buffer,sizeof (Buffer),0,
				(struct sockaddr *)&from,fromlen);
		if (retval == SOCKET_ERROR) {
			fprintf(stderr,"send() failed: error %d\n",WSAGetLastError());
		}
		if (socket_type != SOCK_DGRAM){
			printf("Terminating connection\n");
			closesocket(msgsock);
		}
		else
			printf("UDP server looping back for more requests\n");
		continue;
	}
}
赵4老师 2017-06-28
  • 打赏
  • 举报
回复
仅供参考: MSDN98_1\SAMPLES\VC98\SDK\NETDS\WINSOCK\SIMPLE\SIMPLEC.C
/******************************************************************************\
* simplec.c - Simple TCP/UDP client using Winsock 1.1
*
*       This is a part of the Microsoft Source Code Samples.
*       Copyright 1996-1997 Microsoft Corporation.
*       All rights reserved.
*       This source code is only intended as a supplement to
*       Microsoft Development Tools and/or WinHelp documentation.
*       See these sources for detailed information regarding the
*       Microsoft samples programs.
\******************************************************************************/

#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DEFAULT_PORT 5001
#define DEFAULT_PROTO SOCK_STREAM // TCP

void Usage(char *progname) {
	fprintf(stderr,"Usage\n%s -p [protocol] -n [server] -e [endpoint] \
	-l [iterations]\n",
		progname);
	fprintf(stderr,"Where:\n\tprotocol is one of TCP or UDP\n");
	fprintf(stderr,"\tserver is the IP address or name of server\n");
	fprintf(stderr,"\tendpoint is the port to listen on\n");
	fprintf(stderr,"\titerations is the number of loops to execute\n");
	fprintf(stderr,"\t(-l by itself makes client run in an infinite loop,");
	fprintf(stderr," Hit Ctrl-C to terminate it)\n");
	fprintf(stderr,"Defaults are TCP , localhost and 5001\n");
	WSACleanup();
	exit(1);
}
int main(int argc, char **argv) {

	char Buffer[128];
	char *server_name= "localhost";
	unsigned short port	= DEFAULT_PORT;
	int	retval,	loopflag=0;
	int	i, loopcount,maxloop=-1;
	unsigned int addr;
	int	socket_type	= DEFAULT_PROTO;
	struct sockaddr_in server;
	struct hostent *hp;
	WSADATA	wsaData;
	SOCKET	conn_socket;

	if (argc >1) {
		for(i=1;i <argc;i++) {
			if ( (argv[i][0] ==	'-') || (argv[i][0] == '/') ) {
				switch(tolower(argv[i][1]))	{
					case 'p':
						if (!stricmp(argv[i+1],	"TCP") )
							socket_type	= SOCK_STREAM;
						else if	(!stricmp(argv[i+1], "UDP") )
							socket_type	= SOCK_DGRAM;
						else
							Usage(argv[0]);
						i++;
						break;

					case 'n':
						server_name	= argv[++i];
						break;
					case 'e':
						port = atoi(argv[++i]);
						break;
					case 'l':
						loopflag =1;
						if (argv[i+1]) {
							if (argv[i+1][0] !=	'-')
								maxloop	= atoi(argv[i+1]);
						}
						else
							maxloop	= -1;
						i++;
						break;
					default:
						Usage(argv[0]);
						break;
				}
			}
			else
				Usage(argv[0]);
		}
	}
 
	if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR)	{
		fprintf(stderr,"WSAStartup failed with error %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}
 
	if (port ==	0){
		Usage(argv[0]);
	}

	//
	// Attempt to detect if	we should call gethostbyname() or
	// gethostbyaddr()

	if (isalpha(server_name[0])) {	 /*	server address is a	name */
		hp = gethostbyname(server_name);
	}
	else  {	/* Convert nnn.nnn address to a	usable one */
		addr = inet_addr(server_name);
		hp = gethostbyaddr((char *)&addr,4,AF_INET);
	}
	if (hp == NULL ) {
		fprintf(stderr,"Client: Cannot resolve address [%s]: Error %d\n",
			server_name,WSAGetLastError());
		WSACleanup();
		exit(1);
	}

	//
	// Copy	the	resolved information into the sockaddr_in structure
	//
	memset(&server,0,sizeof(server));
	memcpy(&(server.sin_addr),hp->h_addr,hp->h_length);
	server.sin_family =	hp->h_addrtype;
	server.sin_port	= htons(port);

	conn_socket	= socket(AF_INET,socket_type,0); /*	Open a socket */
	if (conn_socket	<0 ) {
		fprintf(stderr,"Client: Error Opening socket: Error %d\n",
			WSAGetLastError());
		WSACleanup();
		return -1;
	}

	//
	// Notice that nothing in this code	is specific	to whether we
	// are using UDP or	TCP.
	// We achieve this by using	a simple trick.
	//	  When connect() is	called on a	datagram socket, it	does not
	//	  actually establish the connection	as a stream	(TCP) socket
	//	  would. Instead, TCP/IP establishes the remote	half of	the
	//	  (	LocalIPAddress,	LocalPort, RemoteIP, RemotePort) mapping.
	//	  This enables us to use send()	and	recv() on datagram sockets,
	//	  instead of recvfrom()	and	sendto()


	printf("Client connecting to: %s\n",hp->h_name);
	if (connect(conn_socket,(struct	sockaddr*)&server,sizeof(server))
		== SOCKET_ERROR) {
		fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}

	// cook	up a string	to send
	//
	loopcount =0;
	while(1) {
		wsprintf(Buffer,"This is a small test message [number %d]",loopcount++);
		retval = send(conn_socket,Buffer,sizeof(Buffer),0);
		if (retval == SOCKET_ERROR)	{
			fprintf(stderr,"send() failed: error %d\n",WSAGetLastError());
			WSACleanup();
			return -1;
		}
		printf("Sent Data [%s]\n",Buffer);
		retval = recv(conn_socket,Buffer,sizeof	(Buffer),0 );
		if (retval == SOCKET_ERROR)	{
			fprintf(stderr,"recv() failed: error %d\n",WSAGetLastError());
			closesocket(conn_socket);
			WSACleanup();
			return -1;
		}
		//
		// We are not likely to	see	this with UDP, since there is no
		// 'connection' established.
		//
		if (retval == 0) {
			printf("Server closed connection\n");
			closesocket(conn_socket);
			WSACleanup();
			return -1;
		}
		printf("Received %d bytes, data [%s] from server\n",retval,Buffer);
		if (!loopflag){
			printf("Terminating connection\n");
			break;
		}
		else {
			if ( (loopcount	>= maxloop)	&& (maxloop	>0)	)
				break;
		}
	}
	closesocket(conn_socket);
	WSACleanup();
}
xiaohuh421 2017-06-28
  • 打赏
  • 举报
回复
什么叫异步阻塞....... 没有这种说法.
yuhaouestc 2017-06-28
  • 打赏
  • 举报
回复
引用 6 楼 xiaohuh421 的回复:
是否阻塞, 是看socket有没有设置非阻塞模式, 默认创建的socket都是阻塞模式, 需要调用api ioctlsocket设置非阻塞模式. select一般都是为了把非阻塞模式的, 变成阻塞模式. 为何这么做, 为什么不直接使用阻塞模式呢? 因为select可以同时判断多个socket连接中是否有数据可以接收, 阻塞模式做不到. 并且同时也能做到没有数据的时候,阻塞等待有数据才做事情, 不会浪费CPU. 有阻塞模式的相同的好处. 再并且, 还可方便的设置接收超时. 跟阻塞模式一样.
恩,那上面那个程序应该就是同步阻塞的?
xiaohuh421 2017-06-28
  • 打赏
  • 举报
回复
是否阻塞, 是看socket有没有设置非阻塞模式, 默认创建的socket都是阻塞模式, 需要调用api ioctlsocket设置非阻塞模式. select一般都是为了把非阻塞模式的, 变成阻塞模式. 为何这么做, 为什么不直接使用阻塞模式呢? 因为select可以同时判断多个socket连接中是否有数据可以接收, 阻塞模式做不到. 并且同时也能做到没有数据的时候,阻塞等待有数据才做事情, 不会浪费CPU. 有阻塞模式的相同的好处. 再并且, 还可方便的设置接收超时. 跟阻塞模式一样.
worldy 2017-06-28
  • 打赏
  • 举报
回复
同步是阻塞的,异步是非阻塞的,所谓阻塞,就是你发送数据,然后等待返回数据,数据没有返回,就死等,直到数据返回或者超时; 非阻塞是你发出一个接收命令,命令发出后不管数据有没有收到,就执行代码的后面的指令,而当数据返回后,系统发出事件通知你处理接收到的数据,这种模式是非阻塞,是异步的
yuhaouestc 2017-06-27
  • 打赏
  • 举报
回复
感觉是同步阻塞的方式?能不能改成非阻塞呢
网络编程,当然要用到Windows Socket(套接字)技术。Socket相关的操作由一系列API函数来完成,比如socket、bind、listen、connect、accept、send、sendto、recv、recvfrom等。调用这些API函数有一定的先后次序,有些函数的参数还比较复杂,对于开发者来说,不是很好用。于是,微软的MFC提供了两个类:CAsyncSocket和CSocket,极大地方便了Socket功能的使用。   CAsyncSocket类在较低层次上封装了Windows Socket API,并且通过内建一个(隐藏的)窗口,实现了适合Windows应用的异步机制(Windows Socket API默认情况下工作在阻塞模式,不方便直接在消息驱动的Windows程序上使用)。CSocket类从CAsyncSocket类派生,进一步简化了Socket功能的应用。不过很遗憾,正因为这两个类都内建了一个窗口,它们并不是线程安全的(thread-safe);如果要在多线程环境下应用Socket功能,建议自行封装Socket API函数。 基于TCP的socket编程的服务器端程序流程如下: 1、创建套接字 2、将套接字绑定到一个本地地址和端口号上(bind) 3、将套接字设为监听模式,准备接受客户请求(listen) 4、等待客户请求,请求到来时接受请求,建立链接,并返回 一个新的基于此次通信的套接字(accept) 5、用返回的套接字和客户端进行通信(send、recv) 6、返回,等待另一客户请求 7、关闭套接字 基于TCP的socket编程的客户端程序流程如下: 1、创建套接字 2、向服务器端发送请求(connect) 3、和服务器端进行通信(send、recv) 4、关闭套接字 基于UDP的socket编程的服务器端程序流程如下: 1、创建套接字 2、将套接字绑定到本地地址和端口号上(bind) 3、等待接收数据(recvfrom) 4、关闭套接字 基于UDP的socket编程的客户端程序流程如下: 1、创建套接字 2、和服务器端进行通信(sendto) 3、关闭套接字 异步方式指的是发送方不等接收方响应,便接着发下个数据包的通信方式;而同步指发送方发出数据后,等收到接收方发回的响应,才发下一个数据包的通信方式。   阻塞套接字是指执行此套接字的网络调用时,直到成功才返回,否则一直阻塞在此网络调用上,比如调用recv()函数读取网络缓冲区中的数据,如果没有数据到达,将一直挂在recv()这个函数调用上,直到读到一些数据,此函数调用才返回;而阻塞套接字是指执行此套接字的网络调用时,不管是否执行成功,都立即返回。比如调用recv()函数读取网络缓冲区中数据,不管是否读到数据都立即返回,而不会一直挂在此函数调用上。在实际Windows网络通信软件开发中,异步阻塞套接字是用的最多的。平常所说的C/S(客户端/服务器)结构的软件就是异步阻塞模式的。   对于这些概念,初学者的理解也许只能似是而非,我将用一个最简单的例子说明异步阻塞Socket的基本原理和工作机制。目的是让初学者不仅对Socket异步阻塞的概念有个非常透彻的理解,而且也给他们提供一个用Socket开发网络通信应用程序的快速入门方法。操作系统是Windows 98(或NT4.0),开发工具是Visual C++6.0。   MFC提供了一个异步类CAsyncSocket,它封装了异步、阻塞Socket的基本功能,用它做常用的网络通信软件很方便。但它屏蔽了Socket的异步、阻塞等概念,开发人员无需了解异步、阻塞Socket的原理和工作机制。因此,建议初学者学习编网络通信程序时,暂且不要用MFC提供的类,而先用Winsock2 API,这样有助于对异步、阻塞Socket编程机制的理解。
《Windows Sockets网络编程》是WindowsSockets网络编程领域公认的经典著作,由Windows Sockets2.0规范解释小组负责人亲自执笔,权威性毋庸置疑。它结合大量示例,对WindowsSockets规范进行了深刻地解读,系统讲解了WindowsSockets网络编程及其相关的概念、原理、主要命令、操作模式,以及开发技巧和可能的陷阱,从程序员的角度给出了大量的建议和最佳实践,是学习WindowsSockets网络编程不可多得的参考书。   全书分为三部分:第一部分(第1~6章),提供了翔实的背景知识和框架方面的概念,借助于此框架,读者可理解WinSock的具体细节,包括WindowsSockets概述、OSI网络参考模型、TCP/IP协议簇中的协议和可用的服务、WinSock网络应用程序的框架及其工作机制、WinSock的三种操作模式、socket通信机制等;第二部分(第7~12章),以FTP客户端实例为基础介绍了函数实例库,还介绍了客户端程序、服务器程序和DLL中间构件及它们的相应函数,并涵盖socket命令和选项及移植BSDSockets相关事项等;第三部分(第13~17章),介绍了应用程序调试技术和工具,针对应用编程中的陷阱的建议和措施,WinSockAPI的多种操作系统平台,WinSock规范的可选功能和WinSock规范2.0中的所有新功能。 译者序 序 前言 第1章 Windows Sockets概述 1.1 什么是Windows Sockets 1.2 Windows Sockets的发展历史 1.3 Windows Sockets的优势 1.3.1 Windows Sockets是一个开放的标准 1.3.2 Windows Sockets提供源代码可移植性 1.3.3 Windows Sockets支持动态链接 1.3.4 Windows Sockets的优点 1.4 Windows Sockets的前景 1.5 结论 第2章 Windows Sockets的概念 2.1 OSI网络模型 2.2 WinSock网络模型 2.2.1 信息与数据 2.2.2 应用协议 2.3 WinSock中的OSI层次 2.3.1 应用层 2.3.2 表示层 2.3.3 会话层 2.3.4 传输层 2.3.5 网络层 2.3.6 数据链路层 2.3.7 物理层 2.4 模块化的层次框 2.5 服务和协议 2.6 协议和API 第3章 TCP/IP协议服务 3.1 什么是TCP/IP 3.2 TCP/IP的发展历史 3.3 传输服务 3.3.1 无连接的服务:UDP 3.3.2 面向连接的服务:TCP 3.3.3 传输协议的选择:UDP与TCP的对比 3.4 网络服务 3.4.1 IP服务 3.4.2 ICMP服务 3.5 支持协议和服务 3.5.1 域名服务 3.5.2 地址解析协议 3.5.3 其他支持协议 3.6 TCP/IP的发展前景 第4章 网络应用程序工作机制 4.1 客户端-服务器模型 4.2 网络程序概览 4.3 socket的打开 4.4 socket的命名 4.4.1 sockaddr结构 4.4.2 sockaddr_in结构 4.4.3 端口号 4.4.4 本地IP地址 4.4.5 什么是socket名称 4.4.6 客户端socket名称是可选的 4.5 与另一个socket建立关联 4.5.1 服务器如何准备建立关联 4.5.2 客户端如何发起一个关联 4.5.3 服务器如何完成一个关联 4.6 socket之间的发送与接收 4.6.1 在“已连接的”socket上发送数据 4.6.2 在“无连接的”socket上发送数据 4.6.3 接收数据 4.6.4 socket解复用器中的关联 4.7 socket的关闭 4.7.1 closesocket 4.7.2 shutdown 4.8 客户端和服务器概览 第5章 操作模式 5.1 什么是操作模式 5.1.1 不挂机,等待:阻塞 5.1.2 挂机后再拨:阻塞 5.1.3 请求对方回拨:异步 5.2 阻塞模式 5.2.1 阻塞socket 5.2.2 阻塞函数 5.2.3 伪阻塞问题 5.2.4 阻塞钩子函数 5.2.5 阻塞情境 5.2.6 撤销阻塞操作 5.2.7 阻塞操作中的超时 5.2.8 无最少接收限制值 5.2.9 代码示例 5.3 阻塞模式 5.3.1 怎样使socket成为阻塞的 5.3.2 成功与失败不是绝对的 5.3.3 探询而阻塞 5.3.4 显式地避让 5.3.5 代码示例 5.4 异步模式 5.4.1 认识异步函数 5.4.2 撤销异步操作 5.4.3 代码示例 5.4.4 AU_T

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧