关于完成端口,请高人指教!!!

double2 2004-05-02 11:17:05
我测试《win32多线程程序设计》的关于完成端口通讯的例子时。
我不想一次只读取一个字符,而是想读取多个字符时会出现997(i/0操作重叠中)的错误。
请问如何解决?
ReadFile(
(HANDLE)m_pKey->m_Sock,
m_pKey->m_pInBuffer,
5096,
&m_pKey->m_dwInBufLenght,
&m_pKey->m_ovIn
);

还有
GetQueuedCompletionStatus(
m_hCompletionPort,
&m_dwNumRead,
(LPDWORD)&m_pCntx,
&m_lpOverlapped,
INFINITE
);
我的m_dwNumRead总是返回1呢?

整个代码完全参照书中代码,只不过想把一次读取一个改成读取多个。
请各位高人大施援手,谢谢了!!!
...全文
233 19 点赞 打赏 收藏 举报
写回复
19 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
double2 2004-05-14
to nolove2003(滥竽充数) ( ):

比如客户端,传送了100个字节。那么服务器端在接收到100个字节时。
我怎么知道已经接收完了。后面的没有了?

最奇怪的就是,为什么我把一次读取的字符数量加大就会出错?

  • 打赏
  • 举报
回复
nolove2003 2004-05-13
你所指的结束是什么意思?能说的详细点吗?
  • 打赏
  • 举报
回复
alon21 2004-05-12
mark 2
  • 打赏
  • 举报
回复
gaosl11 2004-05-11
mark
  • 打赏
  • 举报
回复
temp3000 2004-05-10
up
  • 打赏
  • 举报
回复
double2 2004-05-10
续(刚刚说我连续发了3贴了,不让发了)


void CreateWorkerThreads()
{
SYSTEM_INFO sysinfo;
DWORD dwThreadId;
DWORD dwThreads;
DWORD i;

GetSystemInfo(&sysinfo);
dwThreads = sysinfo.dwNumberOfProcessors * 2 + 2;
for (i=0; i<dwThreads; i++)
{
HANDLE hThread;
hThread = CreateThread(
NULL, 0, ThreadFunc, NULL, 0, &dwThreadId
);
CloseHandle(hThread);
}
}

//
// Each worker thread starts here.
DWORD WINAPI ThreadFunc(LPVOID pVoid)
{
BOOL bResult;
DWORD dwNumRead;
struct ContextKey *pCntx;
LPOVERLAPPED lpOverlapped;

UNREFERENCED_PARAMETER(pVoid);

// Loop forever on getting packets from
// the I/O completion port.
for (;;)
{
bResult = GetQueuedCompletionStatus(
ghCompletionPort,
&dwNumRead,
&(DWORD)pCntx,
&lpOverlapped,
INFINITE
);

if (bResult == FALSE
&& lpOverlapped == NULL)
{
FatalError(
"ThreadFunc - Illegal call to GetQueuedCompletionStatus");
}

else if (bResult == FALSE
&& lpOverlapped != NULL)
{
// This happens occasionally instead of
// end-of-file. Not sure why.
closesocket(pCntx->sock);
free(pCntx);
fprintf(stderr,
"ThreadFunc - I/O operation failed\n");
}

else if (dwNumRead == 0)
{
closesocket(pCntx->sock);
free(pCntx);
fprintf(stderr, "ThreadFunc - End of file.\n");
}

// Got a valid data block!
// Save the data to our buffer and write it
// all back out (echo it) if we have see a \n
else
{
// Figure out where in the buffer to save the character
char *pch = &pCntx->OutBuffer[pCntx->nOutBufIndex++];
*pch++ = pCntx->InBuffer[0];
*pch = '\0'; // For debugging, WriteFile doesn't care
if (pCntx->InBuffer[0] == '\n')
{
WriteFile(
(HANDLE)(pCntx->sock),
pCntx->OutBuffer,
pCntx->nOutBufIndex,
&pCntx->dwWritten,
&pCntx->ovOut
);
pCntx->nOutBufIndex = 0;
fprintf(stderr, "Echo on socket %x.\n", pCntx->sock);
}

// Start a new read
IssueRead(pCntx);
}
}

return 0;
}


/*
* Call ReadFile to start an overlapped request
* on a socket. Make sure we handle errors
* that are recoverable.
*/
void IssueRead(struct ContextKey *pCntx)
{
int i = 0;
BOOL bResult;
int err;
int numRead;

while (++i)
{
// Request a single character
bResult = ReadFile(
(HANDLE)pCntx->sock,
pCntx->InBuffer,
1,
&numRead,
&pCntx->ovIn
);

// It succeeded immediately, but do not process it
// here, wait for the completion packet.
if (bResult)
return;

err = GetLastError();

// This is what we want to happen, it's not an error
if (err == ERROR_IO_PENDING)
return;

// Handle recoverable error
if ( err == ERROR_INVALID_USER_BUFFER ||
err == ERROR_NOT_ENOUGH_QUOTA ||
err == ERROR_NOT_ENOUGH_MEMORY )
{
if (i == 5) // I just picked a number
{
Sleep(50); // Wait around and try later
continue;
}

FatalError("IssueRead - System ran out of non-paged space");
}

break;
}

fprintf(stderr, "IssueRead - ReadFile failed.\n");
}

//
// Make sure we are running under the right versions
// of Windows NT (3.51, 4.0, or later)
//
void CheckOsVersion()
{
OSVERSIONINFO ver;
BOOL bResult;

ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

bResult = GetVersionEx((LPOSVERSIONINFO) &ver);

if ( (!bResult) ||
(ver.dwPlatformId != VER_PLATFORM_WIN32_NT) )
{
FatalError("ECHOSRV requires Windows NT 3.51 or later.");
}

}

//
// Error handler
//
void FatalError(char *s)
{
fprintf(stdout, "%s\n", s);
exit(EXIT_FAILURE);
}
  • 打赏
  • 举报
回复
cryptonym 2004-05-10
接收线程那?
  • 打赏
  • 举报
回复
double2 2004-05-10
服务器:这是按一个字节接收的。当我改的大了,就会有997的错误。也不能知道什么时候是接收完毕了。

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tchar.h>
#include <string.h>
#include <winsock.h>
#include <io.h>
#include "MtVerify.h"

// Pick a port number that seems to be away from all others
#define SERV_TCP_PORT 5554
#define MAXLINE 512

//
// Structure definition
//

// The context key keeps track of how the I/O
// is progressing for each individual file handle.
struct ContextKey
{
SOCKET sock;
// Input
char InBuffer[4];
OVERLAPPED ovIn;
// Output
int nOutBufIndex;
char OutBuffer[MAXLINE];
OVERLAPPED ovOut;
DWORD dwWritten;
};

//
// Global variables
//

HANDLE ghCompletionPort;

//
// Function prototypes
//

void CreateWorkerThreads();
DWORD WINAPI ThreadFunc(LPVOID pvoid);
void IssueRead(struct ContextKey *pCntx);
void CheckOsVersion();
void FatalError(char *s);

///////////////////////////////////////////////////////

int main(int argc, char *argv[])
{
SOCKET listener;
SOCKET newsocket;
WSADATA WsaData;
struct sockaddr_in serverAddress;
struct sockaddr_in clientAddress;
int clientAddressLength;
int err;

CheckOsVersion();

err = WSAStartup (0x0101, &WsaData);
if (err == SOCKET_ERROR)
{
FatalError("WSAStartup Failed");
return EXIT_FAILURE;
}

/*
* Open a TCP socket connection to the server
* By default, a socket is always opened
* for overlapped I/O. Do NOT attach this
* socket (listener) to the I/O completion
* port!
*/
listener = socket(AF_INET, SOCK_STREAM, 0);
if (listener < 0)
{
FatalError("socket() failed");
return EXIT_FAILURE;
}

/*
* Bind our local address
*/
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(SERV_TCP_PORT);

err = bind(listener,
(struct sockaddr *)&serverAddress,
sizeof(serverAddress)
);
if (err < 0)
FatalError("bind() failed");

ghCompletionPort = CreateIoCompletionPort(
INVALID_HANDLE_VALUE,
NULL, // No prior port
0, // No key
0 // Use default # of threads
);
if (ghCompletionPort == NULL)
FatalError("CreateIoCompletionPort() failed");

CreateWorkerThreads(ghCompletionPort);

listen(listener, 5);

fprintf(stderr, "Echo Server with I/O Completion Ports\n");
fprintf(stderr, "Running on TCP port %d\n", SERV_TCP_PORT);
fprintf(stderr, "\nPress Ctrl+C to stop the server\n");

//
// Loop forever accepting requests new connections
// and starting reading from them.
//
for (;;)
{
struct ContextKey *pKey;

clientAddressLength = sizeof(clientAddress);
newsocket = accept(listener,
(struct sockaddr *)&clientAddress,
&clientAddressLength);
if (newsocket < 0)
{
FatalError("accept() Failed");
return EXIT_FAILURE;
}

// Create a context key and initialize it.
// calloc will zero the buffer
pKey = calloc(1, sizeof(struct ContextKey));
pKey->sock = newsocket;
pKey->ovOut.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
// Set the event for writing so that packets
// will not be sent to the completion port when
// a write finishes.
pKey->ovOut.hEvent = (HANDLE)((DWORD)pKey->ovOut.hEvent | 0x1);

// Associate the socket with the completion port
CreateIoCompletionPort(
(HANDLE)newsocket,
ghCompletionPort,
(DWORD)pKey, // No key
0 // Use default # of threads
);

// Kick off the first read
IssueRead(pKey);
}
return 0;
}
  • 打赏
  • 举报
回复
double2 2004-05-10
客户端:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock.h>


/* Function Prototypes */
void FatalError(char *s);
int writen(SOCKET sock, char *ptr, int nBytes);
int readline(SOCKET sock, char *ptr, int maxlen);
void DoClientLoop(FILE *fp, SOCKET sock);

/* Constants */
#define MAXLINE 512
#define SERVER_TCP_PORT 5554
#define SERVER_ADDRESS "127.0.0.1"


/*
* Error handler
*/
void FatalError(char *s)
{
fprintf(stdout, "%s\n", s);
exit(EXIT_FAILURE);
}

/*
* Write bytes to the port with proper block size handling.
*/
int writen(SOCKET sock, char *ptr, int nBytes)
{
int nleft;
int nwritten;

nleft = nBytes;
while (nleft > 0)
{
nwritten = send(sock,
ptr,
nBytes,
0
);

if (nwritten == SOCKET_ERROR)
{
fprintf(stdout, "Send Failed\n");
exit(1);
}

nleft -= nwritten;
ptr += nwritten;
}

return nBytes - nleft;
}

/*
* Read a line of text of the port. This version
* is very inefficient, but it's simple.
*/
int readline(SOCKET sock, char *ptr, int maxlen)
{
int n;
int rc;
char c;

for (n=1; n<maxlen; n++)
{
if ( ( rc= recv(sock, &c, 1, 0)) == 1)
{
*ptr++ = c;
if (c=='\n')
break;
}
else if (rc == 0)
{
if (n == 1)
return 0;
else
break;
}
else
return -1; /* Error */
}

*ptr = '\0';
return n;
}

int main(int argc, char *argv[])
{
WSADATA WsaData;
SOCKET sock;
struct sockaddr_in serv_addr;
int err;

puts("EchoCli - client for echo server sample program\n");
puts("Type a line of text followed by Return.");
puts("Exit this program by typing Ctrl+Z followed by Return.");

err = WSAStartup(0x0101, &WsaData);
if (err == SOCKET_ERROR)
FatalError("WSAStartup Failed");

/*
* Bind our local address
*/
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
// Use the local host
serv_addr.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
serv_addr.sin_port = htons(SERVER_TCP_PORT);

/*
* Open a TCP socket (an Internet stream socket)
*/

sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
FatalError("socket() failed -- do you have TCP/IP networking installed?");

if (connect(sock, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
FatalError("connect() failed -- is the server running?");

DoClientLoop(stdin, sock);

closesocket(sock);

return EXIT_SUCCESS;
}

/*
* As long as there is input from "fp", copy it to
* the server, read what the server gives back,
* and print it.
*/
void DoClientLoop(FILE *fp, SOCKET sock)
{
int n;
char sendline[MAXLINE];
char recvline[MAXLINE+1];

while (fgets(sendline, MAXLINE, fp) != NULL)
{
n = strlen(sendline);
if (writen(sock, sendline, n) != n)
FatalError("DoClientLoop: writen() error");

n = readline(sock, recvline, MAXLINE);
if (n < 0)
FatalError("DoClientLoop: readline() error");
recvline[n] = '\0';
fputs(recvline, stdout);
}

if (ferror(fp))
FatalError("DoClientLoop: error reading file");
}
  • 打赏
  • 举报
回复
double2 2004-05-10
to nolove2003(滥竽充数) ( ) :

那我怎么知道数据接收完毕了呢?
  • 打赏
  • 举报
回复
cryptonym 2004-05-10
贴代码来看看丫
  • 打赏
  • 举报
回复
nolove2003 2004-05-10
997不是错误,只是说明了数据重叠而已.不影响数据处理;
  • 打赏
  • 举报
回复
double2 2004-05-10
to :cryptonym(挣钱买房娶老婆)

发送程序肯定是一次发送多个的。
  • 打赏
  • 举报
回复
cryptonym 2004-05-09
有没有改你的发送程序丫,发送端就发了一个字符哟。所以这边就收到一个。
  • 打赏
  • 举报
回复
comman_wang 2004-05-09
估计你没有改对地方,应该在线程ThreadFunc中修改(我也不能确定,你试试吧)。
  • 打赏
  • 举报
回复
Deadheart 2004-05-04
mark
  • 打赏
  • 举报
回复
GameWeaverDummy 2004-05-03
丁力
  • 打赏
  • 举报
回复
以下是我现在做毕业设计的代码,用GetOverlappedResult来等待串口读完。
你自己参考一下



DWORD MutithreadSerial::ReadComm(unsigned char *buf, DWORD dwLength,int iCom)
{
DWORD length = 0;
COMSTAT ComStat;
DWORD dwErrorFlags;
Sleep(250);
if(iCom==1)
{
ClearCommError(hCom[0], &dwErrorFlags, &ComStat);
length = min(dwLength, ComStat.cbInQue);

///////////////////////////////////////////////////////////// 测试
// 以下是自己添加代码: 为了解决ReadFile,如果不加ReadFile返回0,
// 加代码,直到读完,返回 length
//////////////////////////////////////////////////////////// 测试
OVERLAPPED osRead = {0};

BOOL l_bWaitingOnRead = FALSE; //用来检测是否在读
osRead.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);
if(osRead.hEvent == NULL)
{
return FAIL;
}
if(!ReadFile(hCom[0], buf, length, &length, &osRead))
{
if(GetLastError() != ERROR_IO_PENDING)
{
length = FAIL;
AfxMessageBox("读失败2,ReadFile"); //测试

}
else
{
l_bWaitingOnRead = TRUE;
}
}
else
{

return length;
}

DWORD l_dwRes;
if(l_bWaitingOnRead)
{
l_dwRes = WaitForSingleObject(osRead.hEvent, 10 * 1000);
switch(l_dwRes)
{
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hCom[0], &osRead, &length, FALSE))
{
length = FAIL;
}
else
{
return length;
}
break;
default:
length = FAIL;
}
}
CloseHandle(osRead.hEvent);
return length;
}
if(iCom==2)
{
ClearCommError(hCom[1], &dwErrorFlags, &ComStat);
length = min(dwLength, ComStat.cbInQue);

///////////////////////////////////////////////////////////// 测试
// 以下是自己添加代码: 为了解决ReadFile,如果不加ReadFile返回0,
// 加代码,直到读完,返回 length
//////////////////////////////////////////////////////////// 测试
OVERLAPPED osRead = {0};

BOOL l_bWaitingOnRead = FALSE; //用来检测是否在读
osRead.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);
if(osRead.hEvent == NULL)
{
return FAIL;
}
if(!ReadFile(hCom[1], buf, length, &length, &osRead))
{
if(GetLastError() != ERROR_IO_PENDING)
{
length = FAIL;
AfxMessageBox("读失败2,ReadFile"); //测试

}
else
{
l_bWaitingOnRead = TRUE;
}
}
else
{

return length;
}

DWORD l_dwRes;
if(l_bWaitingOnRead)
{
l_dwRes = WaitForSingleObject(osRead.hEvent, 10 * 1000);
switch(l_dwRes)
{
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hCom[1], &osRead, &length, FALSE))
{
length = FAIL;
}
else
{
return length;
}
break;
default:
length = FAIL;
}
}
CloseHandle(osRead.hEvent);
return length;
}
  • 打赏
  • 举报
回复
GameWeaverDummy 2004-05-02
丁页
  • 打赏
  • 举报
回复
相关推荐
发帖
网络编程
加入

1.8w+

社区成员

VC/MFC 网络编程
申请成为版主
帖子事件
创建了帖子
2004-05-02 11:17
社区公告
暂无公告