请教:Socket的一个问题

zjsowin 2000-01-21 06:16:00
操作系统:windows98/NT
工具:VC++/C++ Builder
问题:编 写 SOCKET程 序 时 , 如 何 使 用 recv/send接 受 或 发 送 比 指 定 缓 冲 区 大 的 数 据 包 ?
比 如 :
char buf[1024];
ret=send(MySocket, (char FAR *)buf, sizeof(buf), 0);
当 要 发 送 的 数 据 大 于 1024bytes时 , 如 何 控 制 程 序 ? 要 用 到 Out Of Band吗 ?send()和recv()的处理情况应该不同,对吗?
...全文
425 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
yinyu 2000-07-17
  • 打赏
  • 举报
回复
120,如果数据头申明的长度与实际长度不符呢,那整个socket就紊乱了
cxl_langchao 2000-04-05
  • 打赏
  • 举报
回复
不知道用流技术可否解决
120 2000-04-04
  • 打赏
  • 举报
回复
其实多于BUFFER的传送经常有的是,在传输之前,应该先发个头给对方,其中有有欲传送的大小,对方收到头后,会不断的从BUFFER读(其实程序是个死循环),直到读到的字节等于欲传送的长度,当然你最好给包加个号码。
zjsowin 2000-04-03
  • 打赏
  • 举报
回复
vchuman:
你好,我想问你个问题。我看了很多的例子,都提到用select和FD_XXX宏来确定能否接收或发送数据。我觉得如下的代码没错,但在VC下编译运行,总是崩溃。经跟踪,出在FD_ISSET()上,为什么?
int ForwardData (SOCKET ClientSocket)
{

int nRecvLen = 0;
int nRet = 0; // use to get the function return value

char *cbBuf; // the data buffer

// connect to Proxy
SOCKET ProxySocket = socket (AF_INET, SOCK_STREAM, 0);
if (ProxySocket == SOCKET_ERROR)
return (WSAGetLastError ());

struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr(szIP_Server);
sa.sin_port = htons(nPort_Server);
bzero(&(sa.sin_zero), 8);

nRet = connect (ProxySocket, (const struct sockaddr FAR *)&sa, sa_len);
if (nRet == SOCKET_ERROR)
return (WSAGetLastError ());

fd_set sockset;

//FD_ZERO(&socket);
FD_SET ((unsigned int)ClientSocket, &sockset);
FD_SET ((unsigned int)ProxySocket, &sockset);

struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 500;

cbBuf = (char *) malloc (DATASIZE);
if (cbBuf == NULL)
{
printf ("Allocate memory for buffer error\n");
return (-1);
}

for(;;)
{
if (!select (ClientSocket+1, &sockset, NULL, NULL, &tv)) // if expire
{
printf ("select 2nd\n");
select (ProxySocket+1, &sockset, NULL, NULL, &tv); // select another
}

if (FD_ISSET (ClientSocket, &sockset)) // if client socket can read
{
memset (cbBuf, 0, DATASIZE);

nRecvLen = recv (ClientSocket, cbBuf, DATASIZE, 0);
if (nRecvLen == SOCKET_ERROR)
{
free (cbBuf);
return (WSAGetLastError ());
}
else if (nRecvLen == 0)
continue;

nRecvLen = send (ProxySocket, cbBuf, nRecvLen, 0);
if (nRecvLen == SOCKET_ERROR)
{
free (cbBuf);
return (WSAGetLastError ());
}
}

if (FD_ISSET (ProxySocket, &sockset)) // if proxy socket can read
{
memset (cbBuf, 0, DATASIZE);
nRecvLen = recv (ProxySocket, cbBuf, DATASIZE, 0);

if (nRecvLen == SOCKET_ERROR)
{
free (cbBuf);
return (WSAGetLastError ());
}
else if (nRecvLen == 0)
continue;

nRecvLen = send (ClientSocket, cbBuf, nRecvLen, 0);
if (nRecvLen == SOCKET_ERROR)
{
free (cbBuf);
return (WSAGetLastError ());
}
}
} // loop until finish the data transmit.

free (cbBuf);
closesocket (ProxySocket);
}


vchuman 2000-04-02
  • 打赏
  • 举报
回复
缓冲区是一定的,所以必须考虑到传输大于缓冲区的数据。我做过70M的文件传输和实时的每2秒的12KB乘以连接数目的数据传输应用工程。

虽然TCP/IP协议是一个安全协议,但是它并没有完成数据包内!数据的安全检查。例如:你时时发送数据send(...)但是在TCP/IP的数据打包时并不是按照你每次Send的大小发送的,所以在接收时数据会源源不断的发送到接收的响应事件中这样一来你接收道的数据就没有被分割开来而是混在一起。
处理方法在发送时将完成的数据定义好头尾信息(目的是为了在接收时进行分割),在接收端的接收事件中要对带有头尾信息的数据进行组合!这样才可以完成大数据的网络传输。

有问题mailto vcman@163.net
marshell0 2000-03-10
  • 打赏
  • 举报
回复
Above is not the right answer
I think you could change the inner buffer of the socket through this way:
if you use AsynSocket just user its function SetSockOpt(),
Or use Ioctrl() in socket
solomon 2000-03-06
  • 打赏
  • 举报
回复
-->
不管数据是否真有100M,我的意思其实就是solomon的意思。但如果不用MFC的类库,自己编程解决,如何判断是否有数据需要继续传?是判断send()的返回值还是判断别的?
-->
其实TCP可以完全控制数据的可靠性,但是,如果数据出错,只有一个可能,那就是
客户端断开连接,或超时。如果出错,可以从send 的返回值,或 WSGetLastError
(具体函数名忘了)取得,此时,必须退出循环,从新Listen, 然后根据客户端的要求,进行续传。即使用MFC也要这么做,
gun2 2000-03-05
  • 打赏
  • 举报
回复
看得我实在是残不忍睹!

如果你的socket是tcp socket的话,你不必考虑可靠性(其实也不是绝对可靠),如果是udp socket或其他的话,你就得考虑数据丢失的可能了!我不稀罕分数,如果你能把需求大致email给我,我可以试着看能否帮的上忙。

luckroc 2000-01-26
  • 打赏
  • 举报
回复
当你从client端发送出一个数据包,server收到后,可以发回一个应答,而client端在收到应答,进行判断后,再了出下一个数据包,这样虽然慢了一些,但至少是安全的。
至于如何判断是否还有数据要传,我认为WHQ一开始给出的代码,非常简练,而且有效。
zjsowin 2000-01-25
  • 打赏
  • 举报
回复
"tcp/ip会自动为数据打包",这句话我同意.
如果"无须关心buf有多大",那么我的程序为什么recv()时正常,而send()时则总是send不出去呢?谁能告诉我问题何在?与什么相关呢?
xubin_sh 2000-01-25
  • 打赏
  • 举报
回复
用getsockopt加SO_MAX_MSG_SIZE参数,可以取回buf的尺寸
用setsockopt加SO_MAX_MSG_SIZE参数,可以设置buf的尺寸
上次是我说漏了,当面向消息的socket发数据是,buf满回返回
WSAEMSGSIZE的出错消息,当你用的是阻塞型socket则buf满会
阻塞在send()调用上,直到buf可以继续容纳新的数据。注意,
(对阻塞型socket)当对方的socket close以后,你的第一次调用
send()会成功,要到调用第二次调用send()是你才会得到
WSAESHUTDOWN的错误,所以最好,用select得到socket的错误。
WHQ 2000-01-24
  • 打赏
  • 举报
回复
100M?你以为网络是有那么快吗,如果不采用断点续传技术,在国内通过Internet恐怕很难传M以上的数据
limodou 2000-01-24
  • 打赏
  • 举报
回复
使用循环不就行了吗?
solomon 2000-01-24
  • 打赏
  • 举报
回复
你的 100M数据从何而来?硬盘吧,做个循环, 每次读 1024 个字节,发送。
你可以使用 MFC 的 Achive 类(忘了具体的名字,在 CSocker的 Help 中可以找到)
我可以给你一个 sample, 不过现在我的机器坏了(我用的是单位同事的机器)
明天给你吧。
zjsowin 2000-01-24
  • 打赏
  • 举报
回复
这样并不解决办法,如果有100M的数据,难道你要开100M的缓冲区?我的意思是如何通过循环多次传送。关键是如何判断是否有数据需要继续传。
xubin_sh 2000-01-24
  • 打赏
  • 举报
回复
tcp/ip会自动为数据打包,你无须关心buf有多大,out of band不是指数据溢出,而是指带外数据
zjsowin 2000-01-24
  • 打赏
  • 举报
回复
不管数据是否真有100M,我的意思其实就是solomon的意思。但如果不用MFC的类库,自己编程解决,如何判断是否有数据需要继续传?是判断send()的返回值还是判断别的?
WHQ 2000-01-21
  • 打赏
  • 举报
回复
DWORD dwDataSize = 65536; // 该比较大了吧
LPVOID lpDataBuf = new char[dwDataSize];
// 取得数所
LPVOID lpPosition = lpDataBuf;
while( dwDataSize > 0 )
{
memcpy(lpBuf, lpPosition, dwDataSize > 1024 ? 1024 : dwDataSize);
Send(Socket, buf, dwDataSize > 1024 ? 1024 : dwDataSize);
dwDataSize -= 1024;
lpPosition += 1024;
}

69,336

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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