请教: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()的处理情况应该不同,对吗?
...全文
429 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;
}
概述:宠物智能饲养监测系统基于RT-Thread的ART-PI开发板,主控STM32F750XBH6,支持采集温度、湿度和光照数据,实现高温本地和远程预警,智能照明控制,实时采集数据并通过 WIFI 上传云端,针对智能宠物管理提供一个较好的使用范例,也是自己借参加本次活动,首次实操使用RT-Thread rtos,实现功能是次要目的,学习和使用rtt是初衷,之后本项目会继续增加新功能,简单来说这是一个比较实用的。 开发环境硬件:ART-PI 扩展板:DHT11温湿度传感器,BH1750光照传感器和灯控模块 RT-Thread版本:RT-Thread V 4.0.3 开发工具及版本:RT-Thread-studio v2.0.0,STM32CubeMX v6.1.0 RT-Thread使用情况概述内核部分:调度器。 调度器:创建多个线程来实现不同的工作。 组件部分:I2C框架, Sensor框架, SAL 套接字抽象层 I2C框架:使用I2C框架来驱动光照传感器,上层代码可以提高代码的可重用性。 Sensor框架:为上层提供统一的操作接口,提高上层代码的可重用性;简化底层驱动开发的难度,可以非常简单的读取传感器采集数值。 SAL 套接字抽象层:组件完成对不同网络协议栈或网络实现接口的抽象并对上层提供一组标准的 BSD Socket API,这样开发者只需要关心和使用网络应用层提供的网络接口,而无需关心底层具体网络协议栈类型和实现,极大的提高了系统的兼容性,方便开发者完成协议栈的适配和网络相关的开发 软件包部分: Webclient: 提供设备与 HTTP Server 的通讯的基本功能,主要使用http post。 BH1750FVI: 该传感器软件包提供了使用光照强度传感器基本功能,BH1750FVI 是一种用于两线式串行总线接口的数字型光强度传感器集成电路,具有较高的分辨率可以探测较大范围的光强度变化(范围: 1lx-65535lx),特别适合对光照环境要求较高的场景。 硬件框架ART-PI采集到数据上传到云端(目前使用自己php+mysql,断网本地存储测试中)。 软件框架说明上电初始话后,检测传感器变化,满足设定条件的,通过wifi上传到服务器端 目前服务器端只提供数据处理和存储 软件模块说明bh1750_thread_entry: 光照传感器线程 dht11_thread_entry:温湿度传感器线程 user_webclient_post:http_post main:led 闪烁,用来检测当前系统的运行状态。 演示效果视频演示比赛感悟首先非常感谢RTT和电路城以及ST等一起举办的这次活动。 由于第一次使用M7核mcu以及第一次使用rtt操作系统,从小白一步一步学习,测试,看文档,请教,虽然目前还是小白水平,但是确确实实是一次难得的机会,不亲自实践就永远不知道自己的水平在哪,也不能了解rtt便捷。不得不说,结束rtt studio之后,使用起来非常顺手,再者H750 480MHz搭配art-pi强悍的设计,用于之后的复杂功能开发测试有巨大的升级空间。 这次比赛不仅仅是学到了,rtt stm32的软硬件知识,更多的是和许多志同道合的小伙伴,讨论与分享自己的所获所得,这也是一种开源精神。 最后要说声抱歉,鉴于没有充分认识到自己有限的水平,虽然近一个月的时间,还只能写出这样的水平,心比天高无奈水平一般,但是这是一个开始,会围绕设计主题,做持续的更新,不断学习和实践,继续让art-pi发光发热。 感谢!!!

69,371

社区成员

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

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