




已阅读5页,还剩31页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C+Socket编程总结 - 晴阳Blog - 博客园 使用socket写代码主要是要看自己的需求是什么。如果通信时,内容很重要就要使TCP方式。如果用户数太多,可能就要使用UDP方式了。在TCP模式下,最简单的方式就是这样的,使阻塞方式:服务端:1.初始化socket环境,创建socket2.梆定一个端口3.开始监听4.接收客户端5.接收到客户端之后,使用这个socket来与这个客户通信#include stdAfx.h#include #include #include using namespace std;#pragma comment(lib, ws2_32.lib)#pragma comment(lib, mswsock.lib)DWORD IniSOCKDLL()WORD wVersionRequested;WSADATA wsaData;int err=0;wVersionRequested = MAKEWORD( 2, 2 );err = WSAStartup( wVersionRequested, &wsaData ); return err;int main(int argc, char* argv)cout程序开始endl;IniSOCKDLL();SOCKET ss=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,NULL);SOCKADDR_IN addr;int len;addr.sin_family=AF_INET;addr.sin_addr.s_addr = htonl(INADDR_ANY);addr.sin_port = htons(1002);len=sizeof(addr);bind(ss , (PSOCKADDR)&addr , len);listen(ss,5);SOCKET sc=accept(ss,(PSOCKADDR)&addr,&len);char buff1024;ZeroMemory(buff,1024);recv(sc,buff,1024,0);coutbuffendl;ZeroMemory(buff,1024);memcpy(buff,123,3);send(sc,buff,3,0);closesocket(sc);closesocket(ss);return 0;客户端:1.初始化socket环境,创建socket2.连接服务端3.开启一个线程来接收数据4.使用send直接发数据包#include stdAfx.h#include #include #include using namespace std;#pragma comment(lib, ws2_32.lib)#pragma comment(lib, mswsock.lib)DWORD IniSOCKDLL()WORD wVersionRequested;WSADATA wsaData;int err=0;wVersionRequested = MAKEWORD( 2, 2 );err = WSAStartup( wVersionRequested, &wsaData ); return err;int main(int argc, char* argv)IniSOCKDLL();SOCKET sc=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,NULL);SOCKADDR_IN addr;int len;addr.sin_family=AF_INET;addr.sin_addr.s_addr = inet_addr(127.0.0.1);addr.sin_port = htons(1002);len=sizeof(addr);connect(sc, (struct sockaddr *)&addr, len);char buff1024;ZeroMemory(buff,1024);memcpy(buff,123,3);send(sc,buff,3,0);recv(sc,buff,1024,0);coutbuffendl;closesocket(sc);return 0;由这个我们可以做一个这样的模型:为每个阻塞函数开一个线程,让它来处理。这就要留意退出的时候把这一些线程给关闭。当然TCP方式的模型还有事件选择模型。就是把所有的网络事件和我们的一个程序里定义的事件梆定。这个有它的好处,可能可以让我们更好的写一个线程来管理接收与发送。现在来讲一下一个完成端口模型。完成端口一个完成端口其实就是一个通知队列,由操作系统把已经完成的重叠I/O请求的通知放入其中。当某项I/O操作一旦完成,某个可以对该操作结果进行处理的工作者线程就会收到一则通知。而套接字在被创建后,可以在任何时候与某个完成端口进行关联。步骤:1、创建一个空的完成端口;2、得到本地机器的CPU个数;3、开启CPU*2个工作线程(又名线程池),全部都在等待完成端口的完成包;4、创建TCP的监听socket,使用事件邦定,创建监听线程;5、当有人连接进入的时候,将Client socket保存到一个我们自己定义的关键键,并把它与我们创建的完成端口关联;6、使用WSARecv和WSASend函数投递一些请求,这是使用重叠I/O的方式;7、重复56;注:1、重叠I/O的方式中,接收与发送数据包的时候,一定要进行投递请求这是它们这个体系结构的特点当然,在完成端口方式中,不是直接使用的WSARecv和WSASend函数进行请求的投递的。而是使用的ReadFile,Write的方式2、完成端口使用了系统内部的一些模型,所以我们只要按照一定的顺序调用就可以完成了。3、完成端口是使用在这样的情况下,有成千上万的用户连接的时候,它能够保证性能不会降低。#include #include #include #define PORT 5150#define DATA_BUFSIZE 8192/关键项typedef structOVERLAPPED Overlapped;WSABUF DataBuf;CHAR BufferDATA_BUFSIZE;DWORD BytesSEND;DWORD BytesRECV; PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;typedef struct SOCKET Socket; PER_HANDLE_DATA, * LPPER_HANDLE_DATA;DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);void main(void)SOCKADDR_IN InternetAddr;SOCKET Listen;SOCKET Accept;HANDLE CompletionPort;SYSTEM_INFO SystemInfo;LPPER_HANDLE_DATA PerHandleData;LPPER_IO_OPERATION_DATA PerIoData;int i;DWORD RecvBytes;DWORD Flags;DWORD ThreadID;WSADATA wsaData;DWORD Ret;if (Ret = WSAStartup(0x0202, &wsaData) != 0)printf(WSAStartup failed with error %dn, Ret);return;/打开一个空的完成端口if (CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0) = NULL)printf( CreateIoCompletionPort failed with error: %dn, GetLastError();return;/ Determine how many processors are on the system.GetSystemInfo(&SystemInfo);/ 开启cpu个数的2倍个的线程for(i = 0; i Socket = Accept;/与我们的创建的那个完成端口关联起来,将关键项也与指定的一个完成端口关联if (CreateIoCompletionPort(HANDLE) Accept, CompletionPort, (DWORD) PerHandleData,0) = NULL)printf(CreateIoCompletionPort failed with error %dn, GetLastError();return;/ 投递一次接收,由于接收都需要使用这个函数来投递一个接收的准备if (PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA) = NULL)printf(GlobalAlloc() failed with error %dn, GetLastError();return;ZeroMemory(&(PerIoData-Overlapped), sizeof(OVERLAPPED);PerIoData-BytesSEND = 0;PerIoData-BytesRECV = 0;PerIoData-DataBuf.len = DATA_BUFSIZE;PerIoData-DataBuf.buf = PerIoData-Buffer;Flags = 0;if (WSARecv(Accept, &(PerIoData-DataBuf), 1, &RecvBytes, &Flags,&(PerIoData-Overlapped), NULL) = SOCKET_ERROR)if (WSAGetLastError() != ERROR_IO_PENDING)printf(WSARecv() failed with error %dn, WSAGetLastError();return;/工作线程DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)HANDLE CompletionPort = (HANDLE) CompletionPortID;DWORD BytesTransferred;LPOVERLAPPED Overlapped;LPPER_HANDLE_DATA PerHandleData;LPPER_IO_OPERATION_DATA PerIoData;DWORD SendBytes, RecvBytes;DWORD Flags;while(TRUE)/完成端口有消息来了if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,(LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) = 0)printf(GetQueuedCompletionStatus failed with error %dn, GetLastError();return 0;/是不是有人退出了if (BytesTransferred = 0)printf(Closing socket %dn, PerHandleData-Socket);if (closesocket(PerHandleData-Socket) = SOCKET_ERROR)printf(closesocket() failed with error %dn, WSAGetLastError();return 0;GlobalFree(PerHandleData);GlobalFree(PerIoData);continue;/if (PerIoData-BytesRECV = 0)PerIoData-BytesRECV = BytesTransferred;PerIoData-BytesSEND = 0;elsePerIoData-BytesSEND += BytesTransferred;if (PerIoData-BytesRECV PerIoData-BytesSEND)/ Post another WSASend() request./ Since WSASend() is not gauranteed to send all of the bytes requested,/ continue posting WSASend() calls until all received bytes are sent.ZeroMemory(&(PerIoData-Overlapped), sizeof(OVERLAPPED);PerIoData-DataBuf.buf = PerIoData-Buffer + PerIoData-BytesSEND;PerIoData-DataBuf.len = PerIoData-BytesRECV - PerIoData-BytesSEND;if (WSASend(PerHandleData-Socket, &(PerIoData-DataBuf), 1, &SendBytes, 0,&(PerIoData-Overlapped), NULL) = SOCKET_ERROR)if (WSAGetLastError() != ERROR_IO_PENDING)printf(WSASend() failed with error %dn, WSAGetLastError();return 0;elsePerIoData-BytesRECV = 0;/ Now that there are no more bytes to send post another WSARecv() request.Flags = 0;ZeroMemory(&(PerIoData-Overlapped), sizeof(OVERLAPPED);PerIoData-DataBuf.len = DATA_BUFSIZE;PerIoData-DataBuf.buf = PerIoData-Buffer;if (WSARecv(PerHandleData-Socket, &(PerIoData-DataBuf), 1, &RecvBytes, &Flags,&(PerIoData-Overlapped), NULL) = SOCKET_ERROR)if (WSAGetLastError() != ERROR_IO_PENDING)printf(WSARecv() failed with error %dn, WSAGetLastError();return 0;当然TCP方式的模型还有事件选择模型。就是把所有的网络事件和我们的一个程序里定义的事件梆定。这个有它的好处,可能可以让我们更好的写一个线程来管理接收与发送。现在来讲一下一个完成端口模型。完成端口一个完成端口其实就是一个通知队列,由操作系统把已经完成的重叠I/O请求的通知放入其中。当某项I/O操作一旦完成,某个可以对该操作结果进行处理的工作者线程就会收到一则通知。而套接字在被创建后,可以在任何时候与某个完成端口进行关联。步骤:1、创建一个空的完成端口;2、得到本地机器的CPU个数;3、开启CPU*2个工作线程(又名线程池),全部都在等待完成端口的完成包;4、创建TCP的监听socket,使用事件邦定,创建监听线程;5、当有人连接进入的时候,将Client socket保存到一个我们自己定义的关键键,并把它与我们创建的完成端口关联;6、使用WSARecv和WSASend函数投递一些请求,这是使用重叠I/O的方式;7、重复56;注:1、重叠I/O的方式中,接收与发送数据包的时候,一定要进行投递请求这是它们这个体系结构的特点当然,在完成端口方式中,不是直接使用的WSARecv和WSASend函数进行请求的投递的。而是使用的ReadFile,Write的方式2、完成端口使用了系统内部的一些模型,所以我们只要按照一定的顺序调用就可以完成了。3、完成端口是使用在这样的情况下,有成千上万的用户连接的时候,它能够保证性能不会降低。#include #include #include #define PORT 5150#define DATA_BUFSIZE 8192/关键项typedef structOVERLAPPED Overlapped;WSABUF DataBuf;CHAR BufferDATA_BUFSIZE;DWORD BytesSEND;DWORD BytesRECV; PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;typedef struct SOCKET Socket; PER_HANDLE_DATA, * LPPER_HANDLE_DATA;DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);void main(void)SOCKADDR_IN InternetAddr;SOCKET Listen;SOCKET Accept;HANDLE CompletionPort;SYSTEM_INFO SystemInfo;LPPER_HANDLE_DATA PerHandleData;LPPER_IO_OPERATION_DATA PerIoData;int i;DWORD RecvBytes;DWORD Flags;DWORD ThreadID;WSADATA wsaData;DWORD Ret;if (Ret = WSAStartup(0x0202, &wsaData) != 0)printf(WSAStartup failed with error %dn, Ret);return;/打开一个空的完成端口if (CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0) = NULL)printf( CreateIoCompletionPort failed with error: %dn, GetLastError();return;/ Determine how many processors are on the system.GetSystemInfo(&SystemInfo);/ 开启cpu个数的2倍个的线程for(i = 0; i Socket = Accept;/与我们的创建的那个完成端口关联起来,将关键项也与指定的一个完成端口关联if (CreateIoCompletionPort(HANDLE) Accept, CompletionPort, (DWORD) PerHandleData,0) = NULL)printf(CreateIoCompletionPort failed with error %dn, GetLastError();return;/ 投递一次接收,由于接收都需要使用这个函数来投递一个接收的准备if (PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA) = NULL)printf(GlobalAlloc() failed with error %dn, GetLastError();return;ZeroMemory(&(PerIoData-Overlapped), sizeof(OVERLAPPED);PerIoData-BytesSEND = 0;PerIoData-BytesRECV = 0;PerIoData-DataBuf.len = DATA_BUFSIZE;PerIoData-DataBuf.buf = PerIoData-Buffer;Flags = 0;if (WSARecv(Accept, &(PerIoData-DataBuf), 1, &RecvBytes, &Flags,&(PerIoData-Overlapped), NULL) = SOCKET_ERROR)if (WSAGetLastError() != ERROR_IO_PENDING)printf(WSARecv() failed with error %dn, WSAGetLastError();return;/工作线程DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)HANDLE CompletionPort = (HANDLE) CompletionPortID;DWORD BytesTransferred;LPOVERLAPPED Overlapped;LPPER_HANDLE_DATA PerHandleData;LPPER_IO_OPERATION_DATA PerIoData;DWORD SendBytes, RecvBytes;DWORD Flags;while(TRUE)/完成端口有消息来了if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,(LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) = 0)printf(GetQueuedCompletionStatus failed with error %dn, GetLastError();return 0;/是不是有人退出了if (BytesTransferred = 0)printf(Closing socket %dn, PerHandleData-Socket);if (closesocket(PerHandleData-Socket) = SOCKET_ERROR)printf(closesocket() failed with error %dn, WSAGetLastError();return 0;GlobalFree(PerHandleData);GlobalFree(PerIoData);continue;/if (PerIoData-BytesRECV = 0)PerIoData-BytesRECV = BytesTransferred;PerIoData-BytesSEND = 0;elsePerIoData-BytesSEND += BytesTransferred;if (PerIoData-BytesRECV PerIoData-BytesSEND)/ Post another WSASend() request./ Since WSASend() is not gauranteed to send all of the bytes requested,/ continue posting WSASend() calls until all received bytes are sent.ZeroMemory(&(PerIoData-Overlapped), sizeof(OVERLAPPED);PerIoData-DataBuf.buf = PerIoData-Buffer + PerIoData-BytesSEND;PerIoData-DataBuf.len = PerIoData-BytesRECV - PerIoData-BytesSEND;if (WSASend(PerHandleData-Socket, &(PerIoData-
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 合作实验协议合同范本
- 报废汽车回收合同范本
- 警示教育心得体会及感悟(甄选10篇)
- 二八一级考试试题及答案
- 2025年审计实务案例试题及答案
- 地质构造高考试题及答案
- 2025年上海人民法院聘用书记员考试试题及答案
- 2025年山东省医疗卫生系统招聘公共卫生+预防医学训练题及答案
- 2025年饮食问题题库及答案
- 生产要素创新配置催生新质生产力
- 硒鼓基础知识培训内容课件
- 心脏猝死教学课件
- 子宫内膜病理课件
- 棋牌室员工管理制度
- 新课标(水平三)体育与健康《篮球》大单元教学计划及配套教案(18课时)
- 建筑工人临时用工协议书
- 大学生创新创业基础(创新创业课程)完整全套教学课件
- 织造工艺设计指导书
- 冀教版五年级下册数学应用题专项综合练习题
- 鲫鱼的外形与内部解剖
- CPS21F变频恒压供水调节器使用说明书1
评论
0/150
提交评论