c语言发送json格式的socket 怎么发送XML格式的数据

小弟第一次发帖,请大牛们多多捧场!
现在公司要我做一个C语言的SOCKET通信(TCP),要求是千兆网最低50M每秒的传输速度!(S-send&;C&-recv)
小弟试着写了一下,遇到了以下问题:
1,不建立C/S端的缓冲,直接传输,只能传输小文件,遇到大文件就会出错
&&&出现1的问题,是因为发端太快,造成丢包
2,基于1,我想到虽然是流传输,是不是也可以像UDP那样自己自己定义一个校验机制,就是将一个文件切块,然后每一个块加上长度,这样,在传输到C端之后,必须得到C端的确认(也就是C&recv的和块中定义的长度一致),才发下一个块。
&&&&2的方法,是能解决传输大文件的问题,但是速度慢,达不到要求!
3,基于2的问题,我想到,是不是可以在S端自己定义一个缓冲区:
&&&&&&&定义缓冲用了两种方法,一是维护一个链表,动态的定义。二是直接划分出一块内存,静态的缓冲!
&&&&&&&目前正在用3的思路在写代码。
想问问各位大牛们,有什么好的建议!!
欢迎大牛们们发言!
小弟在此谢过!
回复讨论(解决方案)
文件切块,是没有错的。发送端接受端开缓存,也是没有错的
至于lz说的速度慢,可能不是慢在网络IO上:
1:可能是慢在磁盘IO上,也就是你文件内容可能是一边读一边发的,lz可以尝试把文件内容全部读入内存,然后直接对内存中的文件数据分块发送。或者lz可以先做下测试,把你读取文件的代码先去掉,直接malloc分配50M,随便填点数据,然后发送这块内存。如果不慢了,证明是读文件的问题。如果还慢,只能说是你网络代码效率的问题了,比如可以选择换用IOCP模型在做尝试
2:可能是慢在频繁的申请释放内存上,lz可以考虑使用
,给你提供的这个内存池你可以看最后的测试效果,效率相差2个数量级
楼上正解!!
千兆网卡直接send&recv&应该也不会出问题吧,而且速度也应该不会慢,是不是你忘了处理粘包的问题呢?
楼上说的文件分块传输也是可以考虑的,通过多线程发送,接收完毕之后再将文件合并,
IOCP有一个transmitfile&你可以试一下
希望可以帮到你
不知道有多少前人掉在TCP&Socket
send(人多)send(病少)send(财富)
recv(人多病)recv(少财富)
陷阱里面啊!
超过2GB的文件可能需要用到_lseeki64函数。
谢谢,各位大牛,小弟现在就去改代码,今天加个班,明天再向各位求教!
谢谢,各位大牛,小弟现在就去改代码,今天加个班,明天再向各位求教!
解决问题要紧,先别关IOCP一类的了,不然干完需要一段时间了
&&&出现1的问题,是因为发端太快,造成丢包
TCP不会丢包。&
文件切块,是没有错的。发送端接受端开缓存,也是没有错的
至于lz说的速度慢,可能不是慢在网络IO上:
1:可能是慢在磁盘IO上,也就是你文件内容可能是一边读一边发的,lz可以尝试把文件内容全部读入内存,然后直接对内存中的文件数据分块发送。或者lz可以先做下测试,把你读取文件的代码先去掉,直接malloc分配50M,随便填点数据,然后发送这块内存。如果不慢了,证明是读文件的问题。如果还慢,只能说是你网络代码效率的问题了,比如可以选择换用IOCP模型在做尝试
2:可能是慢在频繁的申请释放内存上,lz可以考虑使用
,给你提供的这个内存池你可以看最后的测试效果,效率相差2个数量级
文件IO速度一般比socket&IO快,试试scatter&read,&gather&write,&目的是减少系统调用次数。&&
不知道有多少前人掉在TCP&Socket
send(人多)send(病少)send(财富)
recv(人多病)recv(少财富)
陷阱里面啊!
好熟悉的回复,我以前发帖子你也是这样的回复
昨天有去做测试,发现,并不是IO的问题造成整体的传输慢!还会代码存在问题
我按照自己3的思路去完成代码,也就是在Server端,我分了两个线程,一个线程用于读取文件,并将读到的buf加入到一个动态链表尾部,另一个线程从此链表头取数据,进行send操作,并且对send的返回值进行校验,如果send的返回值和预期的发送字节数不同,则采用断点重传的方式,继续传输。在Client端口,也是用类似的服务端的机制,维护一个链表,进行读取。
需要说明的是:我维护的这个链表是由深度的,并通过深度来调节两个线程对链表的操作。
昨天有去做测试,发现,并不是IO的问题造成整体的传输慢!还会代码存在问题
我按照自己3的思路去完成代码,也就是在Server端,我分了两个线程,一个线程用于读取文件,并将读到的buf加入到一个动态链表尾部,另一个线程从此链表头取数据,进行send操作,并且对send的返回值进行校验,如果send的返回值和预期的发送字节数不同,则采用断点重传的方式,继续传输。在Client端口,也是用类似的服务端的机制,维护一个链表,进行读取。
需要说明的是:我维护的这个链表是由深度的,并通过深度来调节两个线程对链表的操作。
这个思路是可行的的,&注意两个问题:&1.&防止文件IO过快,&导致你的队列(链表)迅速膨胀。&2.&队列(或链表)要有同步机制,&尽量减小临界区。&
个人觉得单线程non-blocking&IO+&synchronous&I/O&multiplexing(select/poll/epoll...)&更好。&
在文件大小相同的前提下:
&读刚读过的文件比头次读没读过的文件快
&读转速快的硬盘上的文件比读转速慢的硬盘上的文件快
&读没有磁盘碎片的文件比读有磁盘碎片的文件快
&读文件不处理比边读边处理快
&单线程从头到尾一次读文件比多线程分别读文件各部分快(非固态硬盘上)
&读固态硬盘上的文件比读普通硬盘上的文件快
昨天有去做测试,发现,并不是IO的问题造成整体的传输慢!还会代码存在问题
我按照自己3的思路去完成代码,也就是在Server端,我分了两个线程,一个线程用于读取文件,并将读到的buf加入到一个动态链表尾部,另一个线程从此链表头取数据,进行send操作,并且对send的返回值进行校验,如果send的返回值和预期的发送字节数不同,则采用断点重传的方式,继续传输。在Client端口,也是用类似的服务端的机制,维护一个链表,进行读取。
需要说明的是:我维护的这个链表是由深度的,并通过深度来调节两个线程对链表的操作。
这个思路是可行的的,&注意两个问题:&1.&防止文件IO过快,&导致你的队列(链表)迅速膨胀。&2.&队列(或链表)要有同步机制,&尽量减小临界区。&
小弟想请问一下,我现在维护一个链表,确实会使得链表的长度在某一个时刻徒增,那么应该如何设置链表的深度(文件200M)同时,发送的块大小是要一个一个的试?还是怎样才能或得更好的传输速度?
第二个问题,您说的同步机制,我理解,但是说减小临界区是什么意思?是说对临界数据的选择尽量使得其数据量小么?
在文件大小相同的前提下:
&读刚读过的文件比头次读没读过的文件快
&读转速快的硬盘上的文件比读转速慢的硬盘上的文件快
&读没有磁盘碎片的文件比读有磁盘碎片的文件快
&读文件不处理比边读边处理快
&单线程从头到尾一次读文件比多线程分别读文件各部分快(非固态硬盘上)
&读固态硬盘上的文件比读普通硬盘上的文件快
赵老师,您说的这句“&单线程从头到尾一次读文件比多线程分别读文件各部分快(非固态硬盘上)”只是针对的读取文件是么?那在我传输的过程中,采用多线程应该是比单线程传输要快一些吧?
谢谢指教!
个人觉得单线程non-blocking&IO+&synchronous&I/O&multiplexing(select/poll/epoll...)&更好。&
牛哥,能说仔细下么?
在文件大小相同的前提下:
&读刚读过的文件比头次读没读过的文件快
&读转速快的硬盘上的文件比读转速慢的硬盘上的文件快
&读没有磁盘碎片的文件比读有磁盘碎片的文件快
&读文件不处理比边读边处理快
&单线程从头到尾一次读文件比多线程分别读文件各部分快(非固态硬盘上)
&读固态硬盘上的文件比读普通硬盘上的文件快
赵老师,您说的这句“&单线程从头到尾一次读文件比多线程分别读文件各部分快(非固态硬盘上)”只是针对的读取文件是么?那在我传输的过程中,采用多线程应该是比单线程传输要快一些吧?
谢谢指教!
每秒50M能达到预期效果吗?
有结果回复下
个人觉得单线程non-blocking&IO+&synchronous&I/O&multiplexing(select/poll/epoll...)&更好。&
牛哥,能说仔细下么?
其实没有必要弄搞那么复杂,直接用send/recv就好了,&只要网络足够通畅,&轻松达到。&我在我的笔记本(10Gbps的网卡)上轻松上90MB/s。&
个人觉得单线程non-blocking&IO+&synchronous&I/O&multiplexing(select/poll/epoll...)&更好。&
牛哥,能说仔细下么?
其实没有必要弄搞那么复杂,直接用send/recv就好了,&只要网络足够通畅,&轻松达到。&我在我的笔记本(10Gbps的网卡)上轻松上90MB/s。&
谢谢各位大牛的回答,因为最近有事,所以结贴晚了,小弟拜谢!
另外:代码已经实现了,速度也能达到70+!&&/&&&&/&&&&/&&
相关函数:send, sendto, recv, recvfrom, recvmsg, socket
头文件:#include &sys/types.h& &&#include &sys/socket.h&
定义函数:int sendmsg(int s, const strcut msghdr *msg, unsigned int flags);
函数说明:sendmsg()用来将数据由指定的socket 传给对方主机. 参数s 为已建立好连线的socket, 如果利用UDP 协议则不需经过连线操作. 参数msg 指向欲连线的数据结构内容, 参数flags 一般默认为0, 详细描述请参考send().
结构msghdr 定义如下:
struct msghdr
& & void *msg_ //Address to send to /receive from .
& & socklen_t msg_ //Length of addres data
& & strcut iovec * msg_ //Vector of data to send/receive into
& & size_t msg_ //Number of elements in the vector
& & void * msg_ //Ancillary dat
& & size_t msg_ //Ancillary data buffer length
& & int msg_ //Flags on received message
返回值:成功则返回实际传送出去的字符数, 失败返回-1, 错误原因存于errno
错误代码:
1、EBADF 参数s 非合法的socket 处理代码.
2、EFAULT 参数中有一指针指向无法存取的内存空间
3、ENOTSOCK 参数s 为一文件描述词, 非socket.
4、EINTR 被信号所中断.
5、EAGAIN 此操作会令进程阻断, 但参数s 的socket 为不可阻断.
6、ENOBUFS 系统的缓冲内存不足
7、ENOMEM 核心内存不足 EINVAL 传给系统调用的参数不正确.
范例:参考sendto().1293人阅读
EXT(190)
以上是服务器端的程序
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2632211次
积分:34757
积分:34757
排名:第109名
原创:476篇
转载:2421篇
评论:213条
(9)(9)(2)(8)(10)(3)(6)(3)(3)(5)(9)(9)(5)(1)(3)(1)(1)(1)(1)(9)(10)(7)(33)(13)(28)(16)(8)(12)(22)(44)(30)(8)(10)(41)(102)(164)(86)(20)(18)(43)(87)(40)(78)(9)(52)(76)(16)(32)(26)(39)(40)(50)(120)(112)(104)(223)(38)(112)(71)(37)(51)(31)(6)(7)(12)(2)(18)(15)(25)(8)(9)(3)(5)(11)(4)(19)(23)(3)(5)(2)(17)(18)(43)(12)(1)(7)(4)(3)(6)(12)(17)(6)(108)(12)(55)(9)(11)(28)(30)(113)(28)(1)最近在进行一些路由软件的编程,发现自己对数据报格式并不是十分清楚,所以就查阅了相关资料,总结如下,供大家参考,也可以称为自己日后的工具。图中括号中的数字代表的是当前域所占的空间大小,单位是bit位。黄色的是数据链路层的头部,一共14字节绿色的部分是IP头部,一般是20字节紫色部分是TCP头部,一般是20字节最内部的是数据包内容黄色部分:链路层目的MAC:当前step目的主机的mac地址源MAC:当前step的源主机的mac地址类型:指定网络层所用的协议类型,通常是IP协议,0x0800绿色部分:网络层,这里用的是IP包头格式版本:记录数据报属于哪一个版本的协议,如IPv4或IPv6首部长度:指明IP头部长度,单位是字,也就是两个字节。该域的值最小为5,就是标准的头部长度;最大为15,表明有扩展部分。服务类型:用来区分不同服务的需要数据报总长:包含IP头部的数据报的总长度。注意,这里不包括链路层的头部,目前最大值是65535字节。分组ID:这个域的作用是当一个大的数据报被拆分时,拆分成的小的数据段的这个域都是一样的。标记:共三个bit,第一个未使用;第二个DF(Don’t Fragment),设置成1表示这个数据包不能被分割,这个是针对路由器的一条指令;第三个MF(MoreFragment),如果一个数据包被分割了,那么除了最后一个分段以外的所有分段都必须设置为1,用来表示后面还有更多的分段没有到达,最后一个设置为0,用来表示分割的段全部到达。段偏移量:这个域有13bit,也就是每一个数据报最多有8192个分段。每一个分段的长度必须是8字节的倍数,也就是说8字节是分段的基本单位,当然分组的最后一个段不做限制。这样最大的数据报长度为8*字节,比目前限制的最大数据报长度还多1,能够满足对网络中所有数据报传送的需求。生存时间:这是一个生存期计数器,最大为255s,但是实际上使用的时候用作跳数计数器,当值为0时数据报被丢弃,用来避免一个数据报过久的逗留在网络中。高层协议:这里和链路层的类型作用相同,用来表示更高层的协议,这个数据报里是TCP首部校验和:IP头部的校验和源IP地址:数据报来源主机的IP地址目的IP地址:数据报目的主机的IP地址紫色部分:传输层,这里用的是TCP协议源端口号:数据报来源主机的端口号目的端口号:数据报目的主机的端口号注意:源IP地址,目的IP地址,源端口号,目的端口号这四个字段唯一的确定了一个TCP链接。TCP序号(sq):发送的TCP的序号,从0开始,实际中这个值就是发送的数据报中内容的字节数,比如我发送的第一个报中sq=0,数据报内容20字节,那么下一个数据报的sq就应该是21。捎带的确认(ack):确认收到上一个数据报,然后act的值是指定自己想要收到的下一个数据报的sq,比如我收到一个数据报的sq=0,数据报内容20字节,那么我的ack就应该是21,用来标明我sq=0,内容为20字节的数据报已经收到,我接下来期望收到的是sq=21的数据报。首部长度:和IP头部的长度域类似,这个域用来标明TCP头部的长度,单位也是字。保留:6bit未使用的域Flag:从左到右,[URG|ACK|PSH|RST|SYN|FIN]ACK设置为1表示前面的确认(ack)是有效的,否则前面的确认应被忽略。PSH表示要求对方在接到数据后立即请求递交给应用程序,而不是缓冲起来直到缓冲区收满为止。RST用于重置一个已经混乱的连接。SYN用于建立连接的过程。在链接请求中,SYN=1和ACK=0表示该数据段没有使用捎带的确认域。链接应答则捎带了一个确认,即SYN=1和ACK=1.本质上SYN位是用来表示CONNECTION REQUEST和CONNECTION ACCEPTED,然后进一步用ACK来区分是请求还是应答,的确很高明。FIN用来释放一个连接。它表示发送方已经没有数据要传输了。然后,在关闭一个连接后,关闭进程可能会在一段不确定的时间内继续接收到数据。SYN和FIN数据段都有TCP序号,从而保证了这两种数据段被按照正确的顺序来进行处理。窗口大小:指定了从被确认的字节算起可以发送多少个字节。要深入理解这个域的含义,可以参看TCP用色控制和慢启动算法http://blog.csdn.net/alexander_xfl/article/details/校验和:校验范围包括TCP头、数据报内容和概念性伪头部。概念性伪头部又包括源IP,目的IP,TCP协议号。紧急指针:指向数据报中紧急数据最后一个字节的下一个字节。
最新教程周点击榜
微信扫一扫}

我要回帖

更多关于 c语言socket编程 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信