SERVER用完成端口
CLIENT用WSAAsyncSelect在Client,如下发送:
//My send function
BOOL MySend( INT tableno, MESSAGEKIND msgkind, CHAR *data )
{
int nret;
DATATRANSFERRED datatransfered;
datatransfered.tableno = tableno;
datatransfered.msgkind = msgkind;
strcpy( datatransfered.data, data );
//nret = send( clientsocket, (CHAR*)&datatransfered, sizeof(DATATRANSFERRED), 0 );
nret = send( clientsocket, (CHAR*)&datatransfered,
sizeof(INT)+strlen(datatransfered.data)+sizeof(MESSAGEKIND), 0 );
if( SOCKET_ERROR==nret )
{
MsgTip( "Send data failed!" );
return FALSE;
}
return TRUE;
}在SERVER如下接收:
//SERVER ---- My send function
BOOL MyRecv( LPPER_IO_OPERATION_DATA periodata, LPPER_HANDLE_DATA perhandledata )
{
DWORD recvbytes;
DWORD flags;
flags = 0;
ZeroMemory(&(periodata->overlapped), sizeof(OVERLAPPED));
//Clean the buffer
ZeroMemory( periodata->buffer, strlen(periodata->buffer) );
periodata->databuf.len = DATA_BUFSIZE;
periodata->databuf.buf = periodata->buffer;
if (WSARecv(perhandledata->persocket, &(periodata->databuf), 1, &recvbytes, &flags,
&(periodata->overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return FALSE;
}
} return TRUE;
}这样能正确收到 结构体数据
但反过来就不行了
问题好像出在对传输数据的赋值:
//clean the buffer
ZeroMemory( datasend, strlen(datasend) );
sprintf( datasend, "%d", i );
datatransferred.tableno = -1; //this field is ignored
datatransferred.msgkind = CONNECT;
strcpy( datatransferred.data, datasend );//以下是想强制转换地址,但用几种方法都不行,得到的periodata->buffer的值是"YYYY" ?????
//strcpy( periodata->buffer, (CHAR*)&datatransferred );
memmove( (void*)periodata->buffer, (void*)(CHAR*)&datatransferred,
sizeof(INT)+sizeof(MESSAGEKIND)+strlen(datatransferred.data) );
MySend( periodata, perhandledata ); -------------------------------------------------------------------
请教怎么正确地从SERVER发送结构体到CLIENT端?
CLIENT用WSAAsyncSelect在Client,如下发送:
//My send function
BOOL MySend( INT tableno, MESSAGEKIND msgkind, CHAR *data )
{
int nret;
DATATRANSFERRED datatransfered;
datatransfered.tableno = tableno;
datatransfered.msgkind = msgkind;
strcpy( datatransfered.data, data );
//nret = send( clientsocket, (CHAR*)&datatransfered, sizeof(DATATRANSFERRED), 0 );
nret = send( clientsocket, (CHAR*)&datatransfered,
sizeof(INT)+strlen(datatransfered.data)+sizeof(MESSAGEKIND), 0 );
if( SOCKET_ERROR==nret )
{
MsgTip( "Send data failed!" );
return FALSE;
}
return TRUE;
}在SERVER如下接收:
//SERVER ---- My send function
BOOL MyRecv( LPPER_IO_OPERATION_DATA periodata, LPPER_HANDLE_DATA perhandledata )
{
DWORD recvbytes;
DWORD flags;
flags = 0;
ZeroMemory(&(periodata->overlapped), sizeof(OVERLAPPED));
//Clean the buffer
ZeroMemory( periodata->buffer, strlen(periodata->buffer) );
periodata->databuf.len = DATA_BUFSIZE;
periodata->databuf.buf = periodata->buffer;
if (WSARecv(perhandledata->persocket, &(periodata->databuf), 1, &recvbytes, &flags,
&(periodata->overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return FALSE;
}
} return TRUE;
}这样能正确收到 结构体数据
但反过来就不行了
问题好像出在对传输数据的赋值:
//clean the buffer
ZeroMemory( datasend, strlen(datasend) );
sprintf( datasend, "%d", i );
datatransferred.tableno = -1; //this field is ignored
datatransferred.msgkind = CONNECT;
strcpy( datatransferred.data, datasend );//以下是想强制转换地址,但用几种方法都不行,得到的periodata->buffer的值是"YYYY" ?????
//strcpy( periodata->buffer, (CHAR*)&datatransferred );
memmove( (void*)periodata->buffer, (void*)(CHAR*)&datatransferred,
sizeof(INT)+sizeof(MESSAGEKIND)+strlen(datatransferred.data) );
MySend( periodata, perhandledata ); -------------------------------------------------------------------
请教怎么正确地从SERVER发送结构体到CLIENT端?
什么是pack?
MANAGER manager; //经理
ASSISTANT assistant;//助理
SECRETARY secretary;//秘书
};
struct WORKSHOP{
int membership; //人员数量
MEMBER *member; //人员
};
struct TEAM{
OFFICE office; //office
WORKSHOP workshop;//车间
};假设要让一个Team集合,则如果直接排下
TEAM{
OFFICE{
manager; //经理
assistant;//助理
secretary;//秘书
}
WORKSHOP{
[membership=10;] //人员数量10,但不是实体
[member;] //人员(注意,这里面只说明是哪个车间,而并没有明确到个人实体)
}
}这将导致一清点人员时,就只有三个人到岗,即经理、助理、秘书,而车间只是挂了个排,说是有多少人,哪个车间,实际上一个人都没有到,如果要这样子调集到另外一个工场去作业,那么...所以这个时候就需要具体到人,并且一一排列下去,从而使得不再是挂个牌虚张声势的团队:
TEAM{
OFFICE{
manager; //经理
assistant;//助理
secretary;//秘书
}
WORKSHOP{
member(01);
member(02);
member(03);
member(04);
member(05);
member(06);
member(07);
member(08);
member(09);
member(10);
}
}这个时候才是一个由13人组成的完整团队。这样子说好象有那么点太过抽象^_^
1.#pragma pack(push) //保存以前的对齐状态
2.#pragma pack(4) //以4字节对齐
3. 1与2可以合并,写作 #pragma pack(push,4)
4. #pragma pack(pop) //pop可以省略在网络传输中:
#pragma pack(push,1) //一般加在相关代码前
......//代码
#pragma pack()
加上了#pragma pack还是没变化
前面的代码弄了半天,然后来一个MySend( periodata, perhandledata );前面赋值并没有perhandledata,并且也不知道MySend的写法如何.其实比较简单点,那么发送和接收就按照上面可用的代码去写(当然IOCP和select写法上面有点点差别,不过这里面没有体现IOCP的代码,所以不好妄加评论^_^).另外最最需要注意的问题就是每次收到数据后,须判断是否一整完整的结构体(多了可以少读,少了就不行,应该再加以等待).
源码比较长,所以也没全帖下面是结构体:
//Message kind enum structure ( the same as the client )
typedef enum { CONNECT, START, WINNER }MESSAGEKIND;
//Data structure transferred ( the same as the client )
typedef struct
{
INT tableno;
MESSAGEKIND msgkind;
CHAR data[DATA_BUFSIZE];
}DATATRANSFERRED;下面是main函数中循环接收的代码:
while(TRUE)
{
if ((acceptsocket = WSAAccept(listensocket, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
{
printf("WSAacceptsocket() failed with error %d\n", WSAGetLastError());
return;
}
// Create a socket information structure to associate with the socket
if ((perhandledata = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR,
sizeof(PER_HANDLE_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
// Associate the acceptsocketed socket with the original completion port.
printf("Socket number %d connected\n", acceptsocket);
perhandledata->persocket = acceptsocket;
if (CreateIoCompletionPort((HANDLE) acceptsocket, completionport, (DWORD) perhandledata,
0) == NULL)
{
printf("CreateIocompletionport failed with error %d\n", GetLastError());
return;
}
// Create per I/O socket information structure to associate with the
// WSARecv call below.
if ((periodata = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
ZeroMemory(&(periodata->overlapped), sizeof(OVERLAPPED));
periodata->bytessend = 0;
periodata->bytesrecv = 0;
periodata->databuf.len = DATA_BUFSIZE;
periodata->databuf.buf = periodata->buffer; //fill the g_everyclien array
for( i=0; i<MAX_CLIENT_NUM; i++ )
{
if( 0==g_everyclient[i].bused )
{
g_everyclient[i].bused = 1;
g_everyclient[i].perhandledata = perhandledata;
g_everyclient[i].periodata = periodata;
g_everyclient[i].clientstate = CONNECTSTATE; break;
}
}
if( MAX_CLIENT_NUM==i )
{
printf( "the server has reached the maximum connection!" );
return;
}
//
printf( "insert index = %d\n", i ); //After a connection, a affirmance need be sent to the client
//clean the buffer ZeroMemory( datasend, strlen(datasend) );
sprintf( datasend, "%d", i );
datatransferred.tableno = -1; //this field is ignored
datatransferred.msgkind = CONNECT;
strcpy( datatransferred.data, datasend ); strcpy( periodata->buffer, (CHAR*)&datatransferred );
//memmove( (void*)periodata->buffer, (void*)(CHAR*)&datatransferred,
//sizeof(INT)+sizeof(MESSAGEKIND)+strlen(datatransferred.data) );
//response the index of g_everyclient[]
MySend( periodata, perhandledata );
}
}下面是worker线程:
DWORD WINAPI ServerWorkerThread(LPVOID completionportID)
{
HANDLE completionport = (HANDLE) completionportID;
DWORD bytestransferred;
LPPER_HANDLE_DATA perhandledata;
LPPER_IO_OPERATION_DATA periodata;
INT ret;
DATATRANSFERRED *pdatatransferred;
while(TRUE)
{
if (GetQueuedCompletionStatus(completionport, &bytestransferred,
(LPDWORD)&perhandledata, (LPOVERLAPPED *) &periodata, INFINITE) == 0)
{
ret = GetLastError();
printf("GetQueuedCompletionStatus failed with error %d\n", ret );
if( ret==ERROR_NETNAME_DELETED ) //ERROR_NETNAME_DELETED = 64L
{
CleanConnection( perhandledata, periodata );
}
return 0;
}
// First check to see if an error has occured on the socket and if so
// then close the socket and cleanup the SOCKET_INFORMATION structure
// associated with the socket. ERROR_NETNAME_DELETED ERROR_INVALID_PARAMETER
if (bytestransferred == 0)
{
CleanConnection( perhandledata, periodata );
continue;
}
// Check to see if the bytesrecv field equals zero. If this is so, then
// this means a WSARecv call just completed so update the bytesrecv field
// with the bytestransferred value from the completed WSARecv() call.
//注意----一下的处理和重叠IO是类似的
if (periodata->bytesrecv == 0)
{
periodata->bytesrecv = bytestransferred;
periodata->bytessend = 0;
pdatatransferred = (DATATRANSFERRED*)periodata->databuf.buf;
//
printf( "Data received1: %d\n\n", pdatatransferred->tableno );
printf( "Data received2: %d\n\n", pdatatransferred->msgkind );
printf( "Data received3: %s\n\n", pdatatransferred->data );
//clean the buffer after use of it
ZeroMemory( periodata->databuf.buf, strlen(periodata->databuf.buf) );
}
else
{
periodata->bytessend += bytestransferred;
}
//if it hasn't sent all the data, then send the rest of them
if ( strlen(periodata->buffer) > periodata->bytessend )
{
MySend( periodata, perhandledata );
}
else
{
periodata->bytesrecv = 0; MyRecv( periodata, perhandledata );
}
}
}下面是收发函数:
//My send function
BOOL MySend( LPPER_IO_OPERATION_DATA periodata, LPPER_HANDLE_DATA perhandledata )
{
DWORD sendbytes;
ZeroMemory(&(periodata->overlapped), sizeof(OVERLAPPED));
periodata->databuf.buf = periodata->buffer + periodata->bytessend;
//
periodata->databuf.len = strlen(periodata->buffer) - periodata->bytessend; //Set the bytesrecv=-1 to indicate that current periodata is sending something
periodata->bytesrecv = -1;
if (WSASend(perhandledata->persocket, &(periodata->databuf), 1, &sendbytes, 0,
&(periodata->overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return FALSE;
}
} return TRUE;
}//SERVER ---- My send function
BOOL MyRecv( LPPER_IO_OPERATION_DATA periodata, LPPER_HANDLE_DATA perhandledata )
{
DWORD recvbytes;
DWORD flags;
flags = 0;
ZeroMemory(&(periodata->overlapped), sizeof(OVERLAPPED));
//Clean the buffer
ZeroMemory( periodata->buffer, strlen(periodata->buffer) );
periodata->databuf.len = DATA_BUFSIZE;
periodata->databuf.buf = periodata->buffer;
if (WSARecv(perhandledata->persocket, &(periodata->databuf), 1, &recvbytes, &flags,
&(periodata->overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return FALSE;
}
} return TRUE;
}
------------------------------------------
其实比较简单点,那么发送和接收就按照上面可用的代码去写
-----------------------------------------------------
就是照着可以的写,但不行啊
-----------------------
具体在哪呢?也要考虑字节序
----------------
何处需要考虑
下面是我所写的一个IOCP处理线程的代码,虽然写得不咋样,不过可以供参考一下. while(1)
{
////////////////////////////////////////////////////////////
//判断当前同步运行之线程数量是否超出用户预期运行之结程数量//
//如果超出该期望值,则判断是否有2个以上线程处于用户数据守 //
//候状态,如果有足够线程等待新的完成例程事件,则结束线程 //
// //
//值得注意的是: //
// 1.完成例程通知线程是使用LIFO的顺序, //
// 也就是最近(后)进入待的线程将得到最大的优先运行权 //
// 主要是考虑到当一个结程长时间不工作时对于操作系统 //
// 则须将分配给该线程的资源转换到磁盘缓冲当中出 //
// 从而提高物理内存的利用率,以预期达到最优的运行效果//
// 2.对于网络(包括所有关联于该完成例程的I/O事件都采用 //
// FIFO的顺序,用以保证数据的顺序性和有效性 //
////////////////////////////////////////////////////////////
if((tcpIOCP->ThreadCount>tcpIOCP->FExpectThreadCount)&&
(tcpIOCP->FActiveThreadCount>2))
{
//将线程置入线程顺收站
//以便让时脉处理例程完成对相关资源的回收,以及关闭相关句柄
tcpIOCP->DumpThread(InternalThreadID);
//结束线程循环,终结线程
break;
} //Active Queued Thread Signal
//增加活动{实际为等待完成例程队列)计数
InterlockedIncrement(&(tcpIOCP->FActiveThreadCount));
//加入完成端口例程处理线程队列,以等待完成例程事件/讯号
bSuccess=GetQueuedCompletionStatus(hIOCP,
&dwIOSize,
(LPDWORD)&lpConnCtx,
&pOverLapped,
INFINITE);
//Inactive Queued Thread Signal
//得到一个完成例程讯号,线程从等待队列中出列
//减少活动{实际为等待完成例程队列)计数
InterlockedDecrement(&(tcpIOCP->FActiveThreadCount)); //No more thread waiting for completion
//and in working State
//and Thread count is lower than the Max count
//Increment One Thread
//为保证至少有一个线程处于等待完成例程的处理结程的队列当中
//将在最大线程的限制范围内,增加实际工作线程
//该值可能会超出用户预期同步运行线程数
if((1>(tcpIOCP->FActiveThreadCount))
&&(tcpIOCP->ThreadCount<(long)MAX_THREAD_NUMBER)
&&(tcpIOCP->FRunningState>LS_SHUTDN))
{
tcpIOCP->AddThread();
} //Terminate thread by PostQueuedCompletionStatus
//线程结束通知,由PostQueuedCompletionStatus发出
//并使得参数lpCompletionKey为NULL
if(lpConnCtx==NULL)
{
break;
} //取得重叠I/O信息扩展结构体(从原型指针当中还原)
lpPerIOData=(LPOVERLAPPEDEX)(pOverLapped); //当一个得到一个完成通知
//并且传输数据量为0表示客户端正常断开
if(bSuccess&&(dwIOSize==0))
{
//减少未决操作引用计数
//该计数主要是为了免除时脉例程处理回收站数据时
//在所有事件完成/取消前将相关的资源释放掉
//而导致MSWINSOCK.DLL内部内存地址访问非法错误
InterlockedDecrement(&(lpPerIOData->LockCount));
//将该连接上下文信息节点移入回收站
//以供资源回收例程进一步处理
tcpIOCP->DumpConnection(lpConnCtx);
//继续处理下一个完成端口通知事件
continue;
} //完成端口未通知相关事件
//则可能是由部分线程自我数量调控
//而自行终结导致在该线程提交的I/O请求被取消
//或者网络异常
if(!bSuccess)
{
/*Here should Print the InternalThreadID
and Previous InternalThread in OVERLAPPEDEX*/
//取得最近错误代码
LastError=GetLastError(); if( LastError!=ERROR_IO_PENDING
//重叠 I/O 操作在进行中。
//Overlapped I/O operation is in progress.
&&LastError!=ERROR_OPERATION_ABORTED
//由于线程退出或应用程序请求,已放弃 I/O 操作。
//The I/O operation has been aborted because of either a thread exit or an application request.
&&LastError!=ERROR_NETNAME_DELETED
//指定的网络名不存在
//The specified network name is no longer available.
&&LastError!=ERROR_INVALID_PARAMETER
//参数不正确
//The parameter is incorrect.
)
continue;
Socket_Error=WSAGetLastError();
switch(LastError)
{
case ERROR_NETNAME_DELETED://指定的网络名不再可用。
case ERROR_INVALID_PARAMETER://参数不正确。
//完成通知队列未弹出不能减少未决操作引用计数
//该计数主要是为了免除时脉例程处理回收站数据时
//在所有事件完成/取消前将相关的资源释放掉
//而导致MSWINSOCK.DLL内部内存地址访问非法错误
//将该连接上下文信息节点移入回收站
//以供资源回收例程进一步处理
tcpIOCP->DumpConnection(lpConnCtx);
//继续处理下一个完成端口通知事件
continue;
}
} //减少未决操作引用计数
//该计数主要是为了免除时脉例程处理回收站数据时
//在所有事件完成/取消前将相关的资源释放掉
//而导致MSWINSOCK.DLL内部内存地址访问非法错误
InterlockedDecrement(&(lpPerIOData->LockCount));
{
case SVR_IO_READ://send then recv
try
{
if(dwIOSize)//有收到数据
//交给数据处理过程进行处理
tcpIOCP->InternalOnReceiveData(lpConnCtx,dwIOSize,lpPerIOData->data);
}
catch(...)
{
}
//更新流量计数,包括当前用户连接的流量统计值
//以及全局流量统计值
tcpIOCP->Lock();
try
{
//更新单连接的总接收流量,超int64时"归零"
if(lpConnCtx->TotalRecv>(MAX_INT64-dwIOSize))
lpConnCtx->TotalRecv=dwIOSize;
else
lpConnCtx->TotalRecv=lpConnCtx->TotalRecv+dwIOSize; //更新全局流量计数
InterlockedExchangeAdd(&(tcpIOCP->BytesRecvPerInterval),dwIOSize); //判断该连接是否已经标示为回收
//进入回收状态的连接将不再提交作业请求
if(true==lpConnCtx->InDumping)
break;
//增加未决传输引用计数
InterlockedIncrement(&(lpPerIOData->LockCount));
}
__finally
{
tcpIOCP->Unlock();
} /*发起新的接收请求,以等待接收用户数据*/
ZeroMemory(lpPerIOData,sizeof(OVERLAPPEDEX));
lpPerIOData->OverLapped.hEvent=NULL;
lpPerIOData->OverLapped.Internal=0;
lpPerIOData->OverLapped.InternalHigh=0;
lpPerIOData->OverLapped.Offset=0;
lpPerIOData->OverLapped.OffsetHigh=0;
lpPerIOData->wbuf.buf=(char*)&(lpPerIOData->data);
lpPerIOData->wbuf.len=MAX_BUF_LEN;
lpPerIOData->oper=SVR_IO_READ;
lpPerIOData->flags=0;
#ifdef __DEBUG
lpPerIOData->WorkingThreadID=InternalThreadID;
#endif
//更新是后作业时间,是方便检测超时无数据传输的连接或非法连接
InterlockedExchange(&(lpConnCtx->LastDataTime),time(0));
nResult=WSARecv(lpConnCtx->sockAccept,
&(lpPerIOData->wbuf),
1,
NULL,
&(lpPerIOData->flags),
&(lpPerIOData->OverLapped),
NULL); if(nResult==SOCKET_ERROR)
{
Socket_Error=WSAGetLastError();
if( Socket_Error!=ERROR_IO_PENDING)
{
//网络错误清理连接
InterlockedDecrement(&(lpPerIOData->LockCount));
tcpIOCP->DumpConnection(lpConnCtx);
}
}
break;
case SVR_IO_WRITE://recv then echo
tcpIOCP->Lock();
try
{
EnterCriticalSection(&(lpConnCtx->ctx_CriticalSection));
try
{
/*更新发送缓冲区的已发送计数
特别用来删除部分已经完成发送的缓冲区*/
LPIODATANode OutDataNode=lpConnCtx->O_DATA;
DWORD SentInByte=dwIOSize;
if(lpConnCtx->TotalSent>(MAX_INT64-SentInByte))
lpConnCtx->TotalSent=SentInByte;
else
lpConnCtx->TotalSent=lpConnCtx->TotalSent+SentInByte;
InterlockedExchangeAdd(&(tcpIOCP->BytesSentPerInterval),dwIOSize);
lpConnCtx->TotalSent=lpConnCtx->TotalSent+dwIOSize;
if(true==lpPerIOData->DataInExtend)
{
lpPerIOData->SentBytes=lpPerIOData->SentBytes+SentInByte;
SentInByte=0;
if(lpPerIOData->SentBytes>=lpPerIOData->Length)
{
lpPerIOData->DataInExtend=false;
lpPerIOData->Length=0;
lpPerIOData->SentBytes=0;
}
}
if(false==lpPerIOData->DataInExtend)
{
while(NULL!=OutDataNode)
{
OutData=OutDataNode->Data;
if(NULL!=OutData)
{
OutData->SentBytes=OutData->SentBytes+SentInByte;
SentInByte=0;
if(OutData->SentBytes>=OutData->Length)
{
OutDataNode->Data=OutData->Next;
FreeEx(OutData);
OutData=NULL;
OutData=OutDataNode->Data;
}
if(NULL!=OutData)
break;
}
if(NULL==OutData)
{
lpConnCtx->O_DATA=OutDataNode->Next;
FreeEx(OutDataNode);
OutDataNode=lpConnCtx->O_DATA;
if(NULL==OutDataNode)
break;
}
}/*End of while*/
}/*End of Not ExtendData*/ if(false==lpPerIOData->DataInExtend&&NULL==OutDataNode)
//无数据待发送则不作为
break;
if(true==lpConnCtx->InDumping)
//该连接已经置回收状态,不再提交作业
break;
//增加未决请求计数
InterlockedIncrement(&(lpPerIOData->LockCount));
}
__finally
{
LeaveCriticalSection(&(lpConnCtx->ctx_CriticalSection));
}
}
__finally
{
tcpIOCP->Unlock();
}
//No sending data
lpPerIOData->oper=SVR_IO_WRITE;
lpPerIOData->flags=0;
lpPerIOData->OverLapped.hEvent=NULL;
lpPerIOData->OverLapped.Internal=0;
lpPerIOData->OverLapped.InternalHigh=0;
lpPerIOData->OverLapped.Offset=0;
lpPerIOData->OverLapped.OffsetHigh=0;
#ifdef __DEBUG
lpPerIOData->WorkingThreadID=InternalThreadID;
#endif
u_long Length;
//Begin=========================O_OverLappedEx=====================//
InterlockedExchange(&(lpConnCtx->LastDataTime),time(0));
if(true==lpPerIOData->DataInExtend)
{
//发送重叠I/O信息扩展结构体内部数据
Length=lpPerIOData->Length-lpPerIOData->SentBytes;
lpPerIOData->wbuf.len=Length;
lpPerIOData->wbuf.buf=(char *)(lpPerIOData->data+lpPerIOData->SentBytes); nResult=WSASend(lpConnCtx->sockAccept,
&(lpPerIOData->wbuf),
1,
NULL,
lpPerIOData->flags,
&(lpPerIOData->OverLapped),
NULL);
}
//End===========================O_OverLappedEx=====================//
//Begin=============================O_DATA=========================//
else
{
//发送重叠I/O信息扩展结构体外的待发送数据
Length=OutData->Length-OutData->SentBytes;
lpPerIOData->wbuf.len=Length;
lpPerIOData->wbuf.buf=(char *)(OutData->Buffer+OutData->SentBytes);
nResult=WSASend(lpConnCtx->sockAccept,
&(lpPerIOData->wbuf),
1,
NULL,
lpPerIOData->flags,
&(lpPerIOData->OverLapped),
NULL);
}
//Begin=============================O_DATA=========================//
if(nResult==SOCKET_ERROR)
{
Socket_Error=WSAGetLastError();
if(Socket_Error!=ERROR_IO_PENDING)
{
//网络错误,清理连接
InterlockedDecrement(&(lpPerIOData->LockCount));
tcpIOCP->DumpConnection(lpConnCtx);
}
}
break;
}/*End of switch*/
}
可惜本人是新手
很多地方看不明白
我再仔细看看刚尝试过使用具体的内存拷贝,本以为应该可以的,但为何不行?//Message kind enum structure ( the same as the client )
typedef enum { CONNECT, START, WINNER }MESSAGEKIND;
//Data structure transferred ( the same as the client )
typedef struct
{
INT tableno;
MESSAGEKIND msgkind;
CHAR data[DATA_BUFSIZE];
}DATATRANSFERRED;
//拷贝
memcpy( periodata->buffer, (CHAR*)&datatransferred.tableno, sizeof(INT) );
memcpy( (periodata->buffer+sizeof(INT)), (CHAR*)&datatransferred.msgkind, sizeof(MESSAGEKIND) );
memcpy( (periodata->buffer+sizeof(INT)+sizeof(MESSAGEKIND)),
(CHAR*)datatransferred.data, strlen(datatransferred.data) );
//datatransferred.data假设为"hello"
//末尾加0 periodata->buffer[strlen(datatransferred.data)+sizeof(INT)+sizeof(MESSAGEKIND)] = 0;