DWORD WINAPI ClientThread(LPVOID lpParam)
{
SOCKET sock = (SOCKET)lpParam;
char szBuffer[DEFAULT_BUFFER];
int iRet, nLeft, idx;
while (true)
{
iRet = recv(sock, szBuffer, DEFAULT_BUFFER, 0);
if (0 == iRet)
break;
else if (SOCKET_ERROR == iRet)
{
cout << "recv() failed:" << WSAGetLastError() << endl;
break;
}
szBuffer[iRet] = '\0';
cout << "The Message Resieved: " << szBuffer << endl;
}
cout << "ClientThread exit!" << endl;
return 0;
}
以上是我在接受一个连接以后 创建的一个线程 lpParam 传进来一个accept()反回来的socket
现在的问题是 客户端发送一次数据 这个服务线程可以接收数据 但是紧接着 在循环中第二次执行recv()时 发生10038(WSAENOTSOCK)错误 为什么呀? recv()只能执行一次???
还请各位指教!
{
SOCKET sock = (SOCKET)lpParam;
char szBuffer[DEFAULT_BUFFER];
int iRet, nLeft, idx;
while (true)
{
iRet = recv(sock, szBuffer, DEFAULT_BUFFER, 0);
if (0 == iRet)
break;
else if (SOCKET_ERROR == iRet)
{
cout << "recv() failed:" << WSAGetLastError() << endl;
break;
}
szBuffer[iRet] = '\0';
cout << "The Message Resieved: " << szBuffer << endl;
}
cout << "ClientThread exit!" << endl;
return 0;
}
以上是我在接受一个连接以后 创建的一个线程 lpParam 传进来一个accept()反回来的socket
现在的问题是 客户端发送一次数据 这个服务线程可以接收数据 但是紧接着 在循环中第二次执行recv()时 发生10038(WSAENOTSOCK)错误 为什么呀? recv()只能执行一次???
还请各位指教!
可是我的好像和你的问题 不大一样!
我的程序很简单 就是 客户端在控制台接收用户输入的字符串 然后 send给 服务端 然后 服务端 接收 显示!
可就是出现这个问题!!请问 recv() 第三个参数的用途是什么? 如果 接收的数据 比DEFAULT_BUFFER小 会产生什么结果?? 是不是这个问题 导致 recv()错误!
cout << "listening..." << endl; while(true)
{
iAddrSize=sizeof(client);
sClient = accept(sListen, (SOCKADDR *)&client, &iAddrSize);
if (INVALID_SOCKET == sClient)
{
cout << "accept() failed:" << WSAGetLastError() << endl;
break;
}
cout << "accept a connect." << endl;
hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)sClient, 0, &dwThreadId);
if (NULL == hThread)
{
cout << "CreateThread() failed :" << GetLastError() << endl;
break;
}
CloseHandle(hThread);
}
以上是我父线程的 代码!
并没有在父线程里关闭连接!
recv和send是在两端的一对操作,你接受了一个数据之后由于对方未放送新的数据过来,而你的while还在循环,造成不能接受。
建议使用CreateIoCompletionPort()将数据放入一个队列中,然后用GetQueuedCompletionStatus()取。从各方面来说应该要好一点吧。
是否正确?
我的套接字应该是正确的 因为第一次接受正确!gujianfei1979(谷谷):
while循环 为什么不能接收? recv不是阻塞的吗? 程序运行到recv 应该阻塞等待呀!
而现在 它没有阻塞 而是出错了 出在哪里呀??
我说了 程序很简单! 给你们看看吧~~
我可没有生气 呵呵~~ 希望大家帮帮忙吧~~
已经好几天了 就是解决不了!!
每次都是在 szBuffer[iRet] = '\0'; 这句执行之后 套接字的值 改变了!服务端!
// 002.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include <iostream>
#include <winsock2.h>using namespace std;#define DEFAULT_PORT 5111
#define DEFAULT_BUFFER 4096DWORD WINAPI ClientThread(LPVOID lpParam)
{
SOCKET sock = (SOCKET)lpParam;
char szBuffer[DEFAULT_BUFFER];
int iRet, nLeft, idx;
cout << "start : " << (int)sock << endl;
while (true)
{
cout << "before recv : " << (int)sock << endl;
iRet = recv(sock, szBuffer, DEFAULT_BUFFER, 0);
cout << "after recv : " << (int)sock << endl;
if (0 == iRet)
break;
else if (SOCKET_ERROR == iRet)
{
cout << "recv() failed:" << WSAGetLastError() << endl;
break;
}
cout << "after if: " << (int)sock << endl;
szBuffer[iRet] = '\0';
cout << "before output : " << (int)sock << endl;
cout << "The Message Resieved: " << szBuffer << endl;
cout << "after output : " << (int)sock << endl;
}
cout << "ClientThread exit!" << endl;
return 0;
}int main(int argc, char* argv[])
{
int iRet, iError, iAddrSize;
SOCKET sListen, sClient;
sockaddr_in local, client;
WSAData wsaData;
HANDLE hThread;
DWORD dwThreadId; iRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (0 != iRet)
{
cout << "iRet:" << iRet << endl;
return 1;
}
cout << "WSAStartup()" << endl; sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (SOCKET_ERROR == sListen)
{
cout << "socket() failed:" << WSAGetLastError() << endl;
return 1;
}
cout << "socket()" << endl;
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(DEFAULT_PORT); if (SOCKET_ERROR == bind(sListen, (SOCKADDR *)&local, sizeof(local)))
{
cout << "bind() failed:" << WSAGetLastError() << endl;
return 1;
}
cout << "bind()" << endl; listen(sListen, 4);
cout << "listening..." << endl; while(true)
{
iAddrSize=sizeof(client);
sClient = accept(sListen, (SOCKADDR *)&client, &iAddrSize);
if (INVALID_SOCKET == sClient)
{
cout << "accept() failed:" << WSAGetLastError() << endl;
break;
}
cout << "accept a connect." << endl;
hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)sClient, 0, &dwThreadId);
if (NULL == hThread)
{
cout << "CreateThread() failed :" << GetLastError() << endl;
break;
}
CloseHandle(hThread);
}
closesocket(sListen); WSACleanup();
cout << "socket is closed" << endl;
return 0;
}
客户端:
// 003.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include <winsock2.h>
#include <iostream>using namespace std;#define DEFAULT_PORT 5111
#define DEFAULT_BUFFER 4096int main(int argc, char* argv[])
{
int iRet;
SOCKET sConnect;
sockaddr_in saServer;
WSAData wsaData;
char strBuffer[DEFAULT_BUFFER] ;//= "asdfierrttsdklfjgka"; iRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (0 != iRet)
{
cout << "WSAStartup() failed:" << iRet << endl;
return 1;
}
cout << "WSAStartup()" << endl; sConnect = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (SOCKET_ERROR == sConnect)
{
cout << "socket() failed:" << WSAGetLastError() << endl;
return 1;
}
cout << "socket()" << endl; saServer.sin_addr.s_addr = inet_addr("192.168.0.1");
saServer.sin_family = AF_INET;
saServer.sin_port = htons(DEFAULT_PORT); iRet = connect(sConnect, (SOCKADDR *)&saServer, sizeof(saServer));
if (SOCKET_ERROR == iRet)
{
cout << "connect() failed:" << WSAGetLastError() << endl;
return 1;
}
cout << "connect()" << endl; for (int i = 1; i < 10; i++)
{
cin >> strBuffer;
iRet = send(sConnect, strBuffer, DEFAULT_BUFFER, 0);
if (SOCKET_ERROR == iRet)
{
cout << "send() failed:" << WSAGetLastError() << endl;
return 1;
}
cout << "send() return!" << endl;
}
cout << "end" << endl;
closesocket(sConnect);
cout << "closesocket() completed!" << endl;
WSACleanup();
return 0;
}很简单是吧! 我是初学者 大家帮忙 看看哪里不对!
你试试在client中
for (int i = 1; i < 10; i++)
{
cin >> strBuffer;
iRet = send(sConnect, strBuffer, DEFAULT_BUFFER, 0);
if (SOCKET_ERROR == iRet)
{
cout << "send() failed:" << WSAGetLastError() << endl;
return 1;
}
//////////////////////
sleep(100);
//////////////
cout << "send() return!" << endl;
}
在server的时候记得在线程中
while (true)
{
cout << "before recv : " << (int)sock << endl;
memset(szBuffer,0,DEFAULT_BUFFER);
iRet = recv(sock, szBuffer, DEFAULT_BUFFER, 0);
cout << "after recv : " << (int)sock << endl;
if (0 == iRet)
break;
else if (SOCKET_ERROR == iRet)
{
cout << "recv() failed:" << WSAGetLastError() << endl;
break;
}
........
个人看法,
去掉 szBuffer[iRet] = '\0'; 这句 程序就正常了!!
问题是 这句是怎么影响到 套接字的呀????
奇怪了!! 请大家解释一下!!
还有 我还是弄不明白 recv() send() 这两个函数中 参数的意思 msdn我看了 感觉说得不明白!
int recv (
SOCKET s,
char FAR* buf,
int len,
int flags
);
len 这个参数 指的是buf的长度?? 那么 如果接收的数据小与len 结果是什么? buf中存放的数据(假设是字符串)是什么样子的? 他会自动在结尾加上“\0”吗? 返回值 代表什么意思? 是buf中数据的个数吗? 这句szBuffer[iRet] = '\0';(目的是在字符串最后一个字符加上“\0”)为什么出错???
int send (
SOCKET s,
const char FAR * buf,
int len,
int flags
);
send中 len代表buf中包含的数据大小 还是buf缓冲区的大小? 如果是数据的大小 那么我的程序iRet = send(sConnect, strBuffer, DEFAULT_BUFFER, 0);这句是不是错了?? 如果这句错了 那么是不是因为 len = DEFAULT_BUFFER 导致了传送了 DEFAULT_BUFFER个数据 接收端接收了DEFAULT_BUFFER个数据 使得szBuffer[iRet](iRet = DEFAULT_BUFFER)溢出了 造成了 套接字错误?
问题就是出在szBuffer[iRet] = '\0'上。
根据你的变量定义
SOCKET sock = (SOCKET)lpParam;
char szBuffer[DEFAULT_BUFFER];
szBuffer[iRet] = '\0'实际上是在sock的地方写了'\0';
因为在C/C++中,数组是的索引是从0开始的,当你的recv读了DEFAULT_BUFFER个数据后,如果调用szBuffer[DEFAULT_BUFFER] = '\0',实际上就是缓冲区溢出了。建议定义为
char szBuffer[DEFAULT_BUFFER + 1];
就好了