admin 管理员组

文章数量: 887018

摘要: 介绍了socket的工作原理,构建出一个适用于Windows和Linux操作系统的、跨平台的网络通信程序,并给出设计原理和开发步骤。整个系统采用客户机/服务器(C/S)模型,在Windows系统中,socket程序利用Visual C#语言编写。Linux系统中的socket程序调用select()函数,则该套接字自动设置为非阻塞方式,从而提高了程序的执行效率。经测试,通信两端的进程能够通过各自的套接字收发消息,从而实现了Windows与Linux平台间的通信。(套接字、跨平台网络通信、客户机/服务器、select()函数)

在工业生产中,人们常把稳定性高的Linux系统运用到工业控制领域,以此来提高控制系统的性能。基于Windows平台开发的软件使用方便,因此工程中的应用软件大多数是以Windows为平台开发的。在一个工业系统中,人们需要同时使用Windows和Linux两种操作系统。为了使两个不同的操作系统能够协同工作并互相传递消息,需要在两者间进行通信。 在日常工作中,Windows作为PC机的操作平台被广泛使用,而Linux也以其开放的优势逐渐被用户采用。在两种系统被普遍使用的前提下,如何实现资源共享就成了一个重要的研究课题,需要实现两个平台间的互相通信以达到资源共享的目的。 基于以上两点,实现Windows与Linux平台间的网络通信有着重要的研究意义。本文通过socket(套接字)编程实现两个系统间的通信,socket是对应TCP/IP协议的最典型的应用开发接口,它提供了不同主机间进程通信的端点。本文阐述了套接字的编程原理,并举例说明如何开发Linux和Windows系统之间的网络通信程序。
1 socket基本原理 1.1 基本socket函数  socket通信涉及的基本函数有:      (1)创建套接字     sockfd=socket(domain, type, protocol);参数domain指定socket地址簇类型,type为套接字类型,protocol指明socket请求的协议,sockfd为套接字返回的文件描述符。     (2)绑定套接字与本地地址信息     bind(sockfd,(struct sockaddr*)&server_addr,sizeof(struct sockaddr));该函数将本地主机地址以及端口号与所创建的套接字绑定起来。     (3)监听连接     listen(sockfd,backlog);此函数表示服务器愿意接收连接,backlog指队列中允许的最大排队请求的个数。      (4)建立连接     connect(sockfd,(struct sockaddr*) &server_addr,sizeof(struct sockaddr));connect用于建立连接,server_addr是保存着服务器IP地址和端口号的数据结构struct sockaddr。      (5)接收连接请求     accept(sockfd,(struct sockaddr*) &client_addr,sizeof(struct sockaddr));用于接收客户机发来的连接请求。      (6)发送数据     send(sockfd,msg,len,flags);将len字节的数据msg发送出去,flags通常为0。     (7)接收数据     recv(sockfd,buf,len,flags);从套接字缓冲区buf中读取len字节长度的数据。      (8)关闭套接字     close(sockfd);用于关闭套接字连接。 1.2 socket通信过程 套接字编程采用客户机/服务器(C/S)模式,连接成功后,双方可以进行通信。通信过程如图1所示。


2 软件设计 为避免使用两台计算机的麻烦,在Windows7系统的PC上安装虚拟机,虚拟机的操作系统是Linux。这样就可以在一台PC上进行通信测试,主机为Windows平台,虚拟机为Linux平台。 整个系统采用客户机/服务器(C/S)模型,将Linux平台作为服务器端,其IP地址为10.33.17.127,端口号为3352。将Windows平台作为客户机端,其IP地址为10.33.17.126。 2.1 Linux平台软件设计 2.1.1 响应连接 分别调用socket()、bind()、listen()和accept()来监听客户机端的连接请求并与之连接。 2.1.2 select函数[4]的使用 select可以完成非阻塞操作,即进程执行此函数时不必等待事件发生。它能够监视select返回的文件描述符的变化情况,通过返回值来判断select函数的执行情况。 首先定义一个集合变量fd_set rfds,分别将标准输入句柄0和当前连接句柄client_fd加入到集合中。先令maxfd为0,再比较client_fd与maxfd的大小,将两者中较大的值赋给maxfd,即将文件描述符的最大值赋予maxfd。设置最大等待时间tv.tv_sec=1,tv.tv_usec=0。 retval=select(maxfd+1,&rfds,NULL,NULL,&tv),通过返回值retval判断文件的读写情况。若retval为-1,则出错;若retval为0,则继续等待;若retval为正值,则文件可读写,可以执行接下来的发送和接收消息的操作。 2.1.3 发送与接收消息 if(FD_ISSET(0,&rfds))用来检查指定文件描述符0是否在该集合rfds中,若满足则执行发送操作。fgets(buf,MAXBUF,stdin)表示将键盘输入的至多MAXBUF个字符的stdin送到buf中,摁下“Enter”键后即可发送。 同理,对于是否接收消息通过if (FD_ISSET(client_fd,&rfds))来判断。 2.1.4 断开连接 若要断开连接,则输入“quit”。通过命令if(!strncasecmp(buf,"quit",4))来判断输入的内容是否为quit。连接断开后,显示框显示“Client has terminated the communication.”。 2.2 Windows平台软件设计 在Windows系统中,使用C#语言来编写socket程序。打开Microsoft Visual Studio 2010,新建一个“Windows窗体应用程序”的项目。在窗体中添加两个button控件,分别为button1(连接)和button2(发送)。并添加4个textBox控件,分别为textBox1(消息显示框)、textBox2(消息输入框)、textBox3(服务器IP地址输入框)和textBox4(服务器端口号输入框)。 2.2.1 请求连接 新建socket,Server和nPort分别表示服务器IP地址和端口号,通过命令socket.Connect(ServerIP,nPort)来连接服务器。 2.2.2 发送与接收消息 定义发送的字符串为Message,将消息输入框textBox2中的内容指定为Message。通过发送命令socket.Send(System.Text.Encoding.Default.GetBytes(Message))进行消息发送。 新建一个byte数组byte[] RecvBuffer,通过socket.Receive(RecvBuffer)将接收到的内容存放到RecvBuffer中。接收成功后,将接收到的内容显示在消息显示框中。
3 运行结果与分析 3.1 编译并执行Linux端程序 gcc server_socket.c-o server_scoket  ./server_socket 3352 Server  此时,服务器端程序准备就绪,等待客户端请求连接。 3.2 启动Windows端的连接   打开Microsoft Visual Studio 2010软件,点击“启动调试”键后弹出窗体界面。点击窗体界面中的“连接”键后,客户机端能够成功连接服务器端。 3.3 实现互相通信 连接成功后,服务器端和客户机端可以自由发送消息。如图2所示,Windows系统中,在窗体界面的“消息输入框”中输入消息,点击“发送”后即可发送。在Linux终端中,输入要发送的消息,点击“Enter”键后进行发送。如图3所示。

3.4 结果分析 结果表明,服务器端和客户机端在成功连接后能够进行通信。在Linux系统中,通信结果在终端显示。在Windows系统中,通信结果在窗体界面中显示。经测试,两个平台间能够完成无数次的收发操作。若要结束通信,在Linux终端中键入“quit”,即断开连接。 本文阐述了Windows与Linux系统的网络传输设计方法,双方采用TCP/IP协议,运用socket 接口来开发网络通信程序。Windows平台利用C#编写socket程序,并通过窗体界面显示通信过程。Linux平台中的socket程序调用select函数,实现非阻塞操作。套接字使得连接在通信两端的进程,能够通过各自的套接字收发消息,从而实现了两个平台间的全双工通信。目前的通信程序只能传送字符串,要真正实现两个系统之间的资源共享与消息传递,还需要它们之间能够传送文件、照片及视频等大数据量的信息,这将是下一阶段的研究重点。

本文标签: 网络通信 平台 SOCKET Windows Linux