




全文预览已结束
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Socket编程的基础和基本过程 一、什么是socket接触网络编程当然要了解socket,socket就是套接字,它的定义是一种软件抽象,用于表达两台机器之间的连接终端。对于一个给定的连接,每台机器上都有一个套接字。有点像我们打电话,用电缆把电话连接起来,中间的物理结构和具体实现过程我们不必了解,只要我们能进行通话即可。当我们进行编程时,需要用到socket接口,socket接口定义了许多函数或例程,我们可以直接调用它们实现网络连接、通信等功能。socket接口为我们建立通信信道,我们可以通过这条通道来与一台或多台计算机进行连接。二、socket编程的基本过程,下面我们介绍的都是以基本的Windows socket API为例:1.建立socket:socket编程,其最基本的步骤就是建立socket,下面来看看建立socket的函数原型:SOCKET socket(int af,int type,int protocol );第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置PF_INET;第二个参数指定要创建的套接字类型,一般分为流套接字和数据报套接字两种类型,流套接字类型为SOCK_STREAM、数据报套接字类型为SOCK_DGRAM;第三个参数指定应用程序所使用的通信协议。该函数如果调用成功就返回新创建的套接字的描述符,如果失败则返回INVALID_SOCKET。套接字描述符是一个整数类型的值。每个进程的进程空间里都有一个套接字描述符表,该表中存放着套接字描述符和套接字数据结构的对应关系。该表中有一个字段存放新创建的套接字的描述符,另一个字段存放套接字数据结构的地址,因此根据套接字描述符就可以找到其对应的套接字数据结构。每个进程在自己的进程空间里都有一个套接字描述符表但是套接字数据结构都是在操作系统的内核缓冲里。2.socket的配置:通过socket函数调用返回一个socket描述符后,在使用socket进行网络传输以前,必须配置该socket。面向客户端的socket通过调用connect函数在socket数据结构中保存本地和远端信息。无连接客户端、服务端以及面向连接socket的服务端通过调用bind函数来配置本地信息。bind函数将socket与本机上的一个端口相关联,随后你就可以在该端口监听服务请求。下面看看connect函数和bind函数:int bind(SOCKET s, const struct sockaddr FAR *name, int namelen );当创建了一个socket以后,套接字数据结构中有一个默认的IP地址和默认的端口号。一个服务程序必须调用bind函数来给其绑定一个IP地址和一个特定的端口号。客户程序一般不必调用bind函数来为其socket绑定IP地址和断口号。该函数的第一个参数指定待绑定的socket描述符;第二个参数指定一个sockaddr结构,该结构是这样定义的:struct sockaddr unsigned short sa_family; char sa_data14; ;sa_family指定地址族,对于TCP/IP协议族的套接字,给其置AF_INET。当对TCP/IP协议族的套接字进行绑定时,我们通常使用另一个地址结构:struct sockaddr_in short sin_family;unsigned short sin_port;struct in_addr sin_addr;char sin_zero8;其中sin_family置AF_INET;sin_port指明端口号;sin_addr结构体中只有一个唯一的字段s_addr,表示IP地址,该字段是一个整数,一般用函数inet_addr把字符串形式的IP地址转换成unsigned long型的整数值后再置给s_addr。有的服务器是多宿主机,至少有两个网卡,那么运行在这样的服务器上的服务程序在为其socket绑定IP地址时可以把htonl(INADDR_ANY)置给s_addr,这样做的好处是不论哪个网段上的客户程序都能与该服务程序通信;如果只给运行在多宿主机上的服务程序的socket绑定一个固定的IP地址,那么就只有与该IP地址处于同一个网段上的客户程序才能与该服务程序通信。我们用0来填充sin_zero数组,目的是让sockaddr_in结构的大小与sockaddr结构的大小一致。3. 实现功能服务器端:需要对绑定的端口进行监听,函数原型如下:int listen( SOCKET s, int backlog );服务程序可以调用listen函数使其流套接字s处于监听状态。Backlog为客户连接请求队列的最大数量。处于监听状态的流套接字s将维护一个客户连接请求队列。执行成功,则返回0;如果执行失败,则返回SOCKET_ERROR。此外,还需要从请求队列中取出最前一个客户请求,需要用到accept()函数:SOCKET accept(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen);服务程序调用accept函数从处于监听状态的流套接字s的客户连接请求队列中取出排在最前的一个客户请求,并且创建一个新的套接字来与客户套接字创建连接通道,如果连接成功,就返回新创建的套接字的描述符,以后与客户套接字交换数据的是新创建的套接字;如果失败就返回INVALID_SOCKET。该函数的第一个参数指定处于监听状态的流套接字;操作系统利用第二个参数来返回新创建的套接字的地址结构;操作系统利用第三个参数来返回新创建的套接字的地址结构的长度。客户端:connect函数:int connect(SOCKET s,const struct sockaddr FAR* name,int namelen);connect函数是为了与远程主机建立直接连接而使用的。该函数的参数是相当清楚的:s是即将在其上建立见解的那个有效的TCP套接字;name是针对TCP(说明连接的服务器)的套接字的结构;namelen则是名字参数的长度。send函数:int send(SOCKET s, const char FAR *buf, int len,int flags );该函数的第一个参数指定发送端套接字描述符;第二个参数指明一个存放应用程序要发送数据的缓冲区;第三个参数指明实际要发送的数据的字节数;第四个参数一般置0。这里只描述同步Socket的send函数的执行流程。当调用该函数时,send先比较待发送数据的长度len和套接字s的发送缓冲区的长度,如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么send就比较s的发送缓冲区的剩余空间和len,如果len大于剩余空间大小send就一直等待协议把s的发送缓冲中的数据发送完,如果len小于剩余空间大小send就仅仅把buf中的数据复制到剩余空间里。如果send函数复制数据成功,就返回实际复制的字节数,如果send在复制数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。要注意send函数把buf中的数据成功复制到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个socket函数就会返回SOCKET_ERROR。(每一个除send外的socket函数在执行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该socket函数就返回SOCKET_ERROR)。注意:send函数客户端和服务器端应用程序都可以用send函数来向TCP连接的另一端发送数据。一般客户端发送请求,服务器端发送应答。 下面还有一个服务器端和客户端都需要的函数recv();int recv(SOCKET s, char FAR *buf, int len, int flags );该函数的第一个参数指定接收端套接字描述符;第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;第三个参数指明buf的长度;第四个参数一般置0。函数调用成功返回实际接收的字节数,如果接收出错则返回SOCKET_ERROR,接受数据时网络中断返回0。4、关闭socket当完成服务或者某任务时,记得请把socket关闭:int closesocket (SOCKET s);三、小结及例子分析1、服务器端的工作流程是这样的:首先调用socket函数建立socket,然后调用bind 函数将socket与本机IP地址和端口进行绑定,接着调用listen对socket进行监听,当调用accpet函数接收到一个连接服务请求时,便生成一个新的socket。服务器显示该客户机的IP地址,并通过新的socket向客户端发送字符串Hello!。最后关闭该socket。服务器端重要部分程序如下:main() int sockfd,client_fd; /*sock_fd:监听socket;client_fd:数据传输socket */struct sockaddr_in my_addr; /* 本机地址信息 */struct sockaddr_in remote_addr; /* 客户端地址信息 */if (sockfd = socket(AF_INET, SOCK_STREAM, 0) = -1) /*创建socket*/printf(socket创建出错!); exit(1);my_addr.sin_family=AF_INET;/*协议族*/my_addr.sin_port=htons(SERVPORT);/*端口设定*/my_addr.sin_addr.s_addr = INADDR_ANY;/*设置的IP地址信息*/ memset(&(my_addr.sin_zero),0,sizeof(my_addr.sin_zero);if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr) /*绑定此socket*/ = -1) printf(bind出错!);exit(1);if (listen(sockfd, BACKLOG) = -1) /*对socket进行监听*/printf(listen出错!);exit(1);while(1) sin_size = sizeof(struct sockaddr_in);if (client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size) = -1) printf(accept出错);continue;printf(received a connection from %sn, inet_ntoa(remote_addr.sin_addr);if (send(client_fd, Hello!, 6, 0) = -1) printf(send出错!);close(client_fd);exit(0);close(client_fd);2、客户端程序流程是这样的:在建立socket以后用connect函数与服务器端连接,连接成功以后用recv函数接收服务器端发来的消息。客户端程序重要部分代码如下:#define SERVPORT 3333#define MAXDATASIZE 100 /*每次最大数据传输量 */main(int argc, char *argv)int sockfd, recvbytes;char bufMAXDATASIZE;struct hostent *host;struct sockaddr_in serv_addr;if (argc h_addr);memset(&(my_add
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 船舶租赁合同标准模板
- 施工合同支付监理细则试卷教案(2025-2026学年)
- 英语教师胜任力提升培训资料及测试题
- 酒店前厅智能客户服务系统开发方案
- 旅游行业员工岗位培训手册
- 餐饮企业食材采购质量控制流程
- (正式版)DB32∕T 5179-2025 《智能建筑工程检测与施工质量验收规程》
- (正式版)DB21∕T 4168-2025 《杨树林下射干栽培技术规程》
- 小学数学质数与合数教学案例
- 合同担保保证合同(标准版)
- 北师大版六年级数学上册第一单元圆单元检测(含答案)
- 2025年陕西省法院书记员招聘笔试题库附答案
- 3.1 列代数式表示数量关系(第 1 课时)说课稿人教版七年级数学上册
- 托班服务协议书标准版5篇
- 安全应急预案编制培训课件
- 青少年社会化实践教育模式研究
- 智能测绘课件
- 2025至2030中国乳房重建和隆胸行业发展趋势分析与未来投资战略咨询研究报告
- 2025年70周岁以上老年人换长久驾照三力测试题库(含答案)
- AMZ123《2025上半年跨境电商行业报告》
- 数据赋能打造精准教学新模式
评论
0/150
提交评论