




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
CSOCKET是阻塞的. 我是从来没用过. 按以前见过的一些高手(如OLDWORM)的建议, 绝对不要使用CSOCKET.会给你带来无穷无尽的烦恼(OLDWORM原话).CSocket是基于消息的,所以,需要窗口的支持对Csocket你只能在MFC程序中应用而且不能在线程中对其操作,不然肯定会出现这样那样的错误。这主要和它保存消息接收窗口的句柄有关系。socket是比较低层的,你可以设置其通信模式,相对比较灵活。可以自己控制。当然也也可以把它设置成和CSocket形式,全看你怎么选择。/发送端typedef struct myStrchar str100;int i;double m,CString mystring;mystr,*mystr;.myStr sendstr;send(sockid,(char*)sendstr,sizeof(myStr),0);/接收端,同样定义这个结构体typedef struct myStrchar str100;int i;double m,CString mystring;mystr,*mystr;.myStr *recvstr; /注意,在这里用指针char recvbuf1024;recv(sockid,recvbuf,1024,0);recvstr = (myStr*)recvbuf;在这里已经完成,数据已经填充到了recvstr这个指针中了刚才查了一下书。 Socket缓冲区是分为,接收缓冲和发送缓冲的。 接收缓冲可以直接设置大小,用 int maxsize=1024; setsockopt(socket,SOL_SOCKET,SO_RCVBUF,(int*)&maxsize,sizeof(int); 发送缓冲区大小: int maxsize=1024; setsockopt(socket,SOL_SOCKET,SO_SNDBUF,(int*)&maxsize,sizeof(int); 我是参考书上的,没试过,不知道能不能成功。 另外,也可以把缓冲区的大小设置成0,这样数据就不会通过内存来复制一次,在一定的情况下会提高性能。不过通常都不这样做。1.IP首部用16位来表示IP包的长度,所以IP包最大限制是216即64K。 2.Socket缓冲区分为接收缓冲和发送缓冲,默认值分别如下,在winsock2.h中定义。 #define SO_SNDBUF 0x1001 /* send buffer size */ #define SO_RCVBUF 0x1002 /* receive buffer size */据我所理解,根据OSI模型,数据包并不会在应用层进行分割.Send发送数据如果实际发送的字节数少于要发送的数据数,send函数本身不会自动调用一次send进行第二次发送.假如你发送一个1024K的数据包,但是传输层的最大传输单元只有1K,那么send依然能发送成功,只是数据包会在传输层被分成1024个包了.数据包分段控制是根据网络(传输层)的最大传输单元来控制的,而对应用层不会处理.你的误解可能由此产生.异步SOCKET编程-发送和接收数据转 我本想把发送和接收分开作为两部分,但是最后我决定只略微解释一下 FD_READ ,留下更多的时间来说明更复杂的 FD_WRITE , FD_READ 事件非常容易掌握. 当有数据发送过来时, WinSock 会以 FD_READ 事件通知你, 对于每一个 FD_READ 事件, 你需要像下面这样调用 recv() :int bytes_recv = recv(wParam, &data, sizeof(data), 0);基本上就是这样, 别忘了修改上面的 wParam. 还有, 不一定每一次调用 recv() 都会接收到一个完整的数据包, 因为数据可能不会一次性全部发送过来. 所以在开始处理接收到的数据之前, 最好对接收到的字节数 ( 即 recv() 的返回值) 进行判断, 看看是否收到的是一个完整的数据包.但是,发送端发送数据的长度决定了接收端的recv()函数返回值。FD_WRITE 相对来说就麻烦一些. 首先, 当你建立了一个连接时, 会产生一个 FD_WRITE 事件. 但是如果你认为在收到 FD_WRITE 时调用 send() 就万事大吉, 那就错了. FD_WRITE 事件只在发送缓冲区有多出的空位, 可以容纳需要发送的数据时才会触发.上面所谓的发送缓冲区,是指系统底层提供的缓冲区. send() 先将数据写入到发送缓冲区中, 然后通过网络发送到接收端. 你或许会想, 只要不把发送缓冲区填满, 让发送缓冲区保持足够多的空位容纳需要发送的数据, 那么你就会源源不断地收到 FD_WRITE 事件了. 嘿嘿, 错了.上面只是说 FD_WRITE 事件在发送缓冲区有多出的空位时会触发, 但不是在有足够的空位时触发, 就是说你得先把发送缓冲区填满.通常的办法是在一个无限循环中不断的发送数据, 直到把发送缓冲区填满. 当发送缓冲区被填满后, send() 将会返回 SOCKET_ERROR , WSAGetLastError() 会返回 WSAWOULDBLOCK . 如果当前这个 SOCKET 处于阻塞(同步)模式, 程序会一直等待直到发送缓冲区空出位置然后发送数据; 如果SOCKET是非阻塞(异步)的,那么你就会得到 WSAWOULDBLOCK 错误. 于是只要我们首先循环调用 send() 直到发送缓冲区被填满, 然后当缓冲区空出位置来的时候, 系统就会发出FD_WRITE事件. 有没有想过我能指出这一点来是多么不容易, 你可真走运. 下面是一个处理 FD_WRITE 事件的例子.case FD_WRITE: / 可以发送数据了/ 进入无限循环while(TRUE)/ 从文件中读取数据, 保存到 packet.data 里面.in.read(char*)&packet.data, MAX_PACKET_SIZE);/ 发送数据if (send(wparam, (char*)(&packet), sizeof(PACKET), 0) = SOCKET_ERROR)if (WSAGetLastError() = WSAEWOULDBLOCK)/ 发送缓冲区已经满了, 退出循环.break;else / 其他错误/ 显示出错信息然后退出.CleanUp();return(0); break;看到了吧, 实现其实一点也不困难. 你只是弄混了一些概念而已. 使用这样的发送方式, 在发送缓冲区变满的时候就可以退出循环. 然后, 当缓冲区空出位置来的时候, 系统会触发另外一个 FD_WRITE 事件, 于是你就可以继续发送数据了.在你开始使用新学到的知识之前, 我还想说明一下 FD_WRITE 事件的使用时机. 如果你不是一次性发送大批量的数据的话, 就别想着使用 FD_WRITE 事件了, 原因很简单 - 如果你寄期望于在收到 FD_WRITE 事件时发送数据, 但是却又不能发送足够的数据填满发送缓冲区, 那么你就只能收到连接刚刚建立时触发的那一次 FD_WRITE - 系统不会触发更多的 FD_WRITE 了. 所以当你只是发送尽可能少的数据的时候, 就忘掉 FD_WRITE 机制吧, 在任何你想发送数据的时候直接调用 send() .结论这是我写过的最长的一篇文章. 我也曾试图尽可能把它写短一些来吸引你的注意力, 但是有太多的内容要包括. 在刚刚使用异步SOCKET 时, 如果你没有正确地理解它, 真的会把自己搞胡涂. 我希望我的文章教会了你如何使用它们. _这是我在 GOOGLE 上搜到的一篇文章中的一部分. 虽然原作者的部分观点似乎并不正确, 但是文章写得很易懂. 其实, 如果你想收到 FD_WRITE事件而你又无法先填满发送缓冲区, 可以调用 WSAAsyncSelect( ., FD_WRITE ). 如果当前发送缓冲区有空位, 系统会马上给你发 FD_WRITE 事件.FD_WRITE 消息, MFC 的 CAsyncSocket 类将其映射为 OnSend() 函数. FD_READ 消息, 被映射为 OnReceive() 函数. 三、典型过程图2.1 面向连接的套接字的系统调用时序图2.2 无连接协议的套接字调用时序图与socket有关的一些函数介绍1、读取当前错误值:每次发生错误时,如果要对具体问题进行处理,那么就应该调用这个函数取得错误代码。 int WSAGetLastError(void ); #define h_errno WSAGetLastError()错误值请自己阅读Winsock2.h。2、将主机的unsigned long值转换为网络字节顺序(32位):为什么要这样做呢?因为不同的计算机使用不同的字节顺序存储数据。因此任何从Winsock函数对IP地址和端口号的引用和传给Winsock函数的IP地址和端口号均时按照网络顺序组织的。 u_long htonl(u_long hostlong); 举例:htonl(0)=0 htonl(80)=将unsigned long数从网络字节顺序转换位主机字节顺序,是上面函数的逆函数。 u_long ntohl(u_long netlong); 举例:ntohl(0)=0 ntohl(1342177280)= 804、将主机的unsigned short值转换为网络字节顺序(16位):原因同2: u_short htons(u_short hostshort); 举例:htonl(0)=0 htonl(80)= 204805、将unsigned short数从网络字节顺序转换位主机字节顺序,是上面函数的逆函数。 u_short ntohs(u_short netshort); 举例:ntohs(0)=0 ntohsl(20480)= 806、将用点分割的IP地址转换位一个in_addr结构的地址,这个结构的定义见笔记(一),实际上就是一个unsigned long值。计算机内部处理IP地址可是不认识如192.1.8.84之类的数据。 unsigned long inet_addr( const char FAR * cp ); 举例:inet_addr(192.1.8.84)=1409810880 inet_addr(127.0.0.1)= 16777343如果发生错误,函数返回INADDR_NONE值。7、将网络地址转换位用点分割的IP地址,是上面函数的逆函数。 char FAR * inet_ntoa( struct in_addr in ); 举例:char * ipaddr=NULL; char addr20; in_addr inaddr; inaddr. s_addr=16777343; ipaddr= inet_ntoa(inaddr); strcpy(addr,ipaddr); 这样addr的值就变为127.0.0.1。注意意不要修改返回值或者进行释放动作。如果函数失败就会返回NULL值。8、获取套接字的本地地址结构: int getsockname(SOCKET s, struct sockaddr FAR * name, int FAR * namelen ); s为套接字 name为函数调用后获得的地址值 namelen为缓冲区的大小。 9、获取与套接字相连的端地址结构: int getpeername(SOCKET s, struct sockaddr FAR * name, int FAR * namelen ); s为套接字 name为函数调用后获得的端地址值 namelen为缓冲区的大小。 10、获取计算机名: int gethostname( char FAR * name, int namelen ); name是存放计算机名的缓冲区 namelen是缓冲区的大小 用法: char szName255; memset(szName,0,255); if(gethostname(szName,255)=SOCKET_ERROR) /错误处理 返回值为:szNmae=xiaojin 11、根据计算机名获取主机地址: struct hostent FAR * gethostbyname( const char FAR * name )
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【正版授权】 ISO/IEC TR 16088:2025 EN Information technology - Computer graphics,image processing and environmental representation - Constructs for visual positioning systems in mixed a
- 【正版授权】 ISO/IEC 23001-17:2024/Amd 1:2025 EN Information technology - MPEG systems technologies - Part 17: Carriage of uncompressed video and images in ISO base media file format - A
- 【正版授权】 ISO 29461-4:2025 EN Air intake filter systems for rotary machinery - Part 4: Test methods for static filter systems in coastal and offshore environments
- 【正版授权】 ISO 8168:2025 EN Aerospace - Bolts,with MJ threads,made of heat and corrosion resisting steel,strength class 1 100 MPa - Procurement specification
- 【正版授权】 ISO 5059-1:2025 EN Geometrical product specifications (GPS) - Dimensional measuring equipment - Part 1: Design and metrological characteristics of two-point inside micromete
- 【正版授权】 ISO 12234-1:2025 EN Digital imaging - Image storage - Part 1: Reference model
- 【正版授权】 IEC 61035-2-2:1993 EN-D Specification for conduit fittings for electrical installations - Part 2: Particular specifications - Section 2: Conduit fittings of insulating mater
- 北方大棚种植知识培训课件
- 出纳实训考试试题及答案
- 北京高尔夫入门知识培训课件
- 肿瘤科五年发展规划
- 文化传播公司创业计划书范本
- 2025装修半包工合同样本
- DB42T 1585-2020 规模化牛场生物安全技术规范
- 学校“十五五”五年发展规划(2026-2030年):深植教育沃土培厚发展根基
- 2025年物业能力评级考试题库
- 2025年行政执法证考试必考题库(含答案)
- 盆底相关知识课件
- 重庆巴川量子中学2024-2025学年数学八年级第一学期期末综合测试试题含解析
- 2025年行政执法考试题库及答案大全
- 基本药物知识课件
评论
0/150
提交评论