工作站与PC之间进程的实时通讯

时间:2022-06-18 05:21:47

工作站与PC之间进程的实时通讯

摘 要 该文简要介绍了sun工作站与pc之间进行通讯的常用方法,着重论述了一种基于socket编程,实现进程间直接实时通讯的方法,并举例说明。

随着计算机的日益普及和应用领域的不断扩展,人们对计算机性能的要求也越来越高,特别是在科学计算、图形图像处理、网络工程、计算机辅助设计和制造(cad/cam)以及软件工程等领域。这些领域的要求对于一般的微型计算机来说是难以胜任的,而工作站的出现又恰好满足了这些方面的需要。sun工作站是工作站中的典型代表,由于它采用了risc技术等一系列先进的技术和方法,使得其性能价格比远远超出传统的微、小型计算机系统,因而具有很高的市场占有率。另一方面,ibm pc及其兼容机在我国也相当普遍,它们在各行各业得到了广泛的应用,拥有众多的用户和软硬件产品。

如何将sun工作站与pc这两者之间有机地结合起来,使它们各尽其长,就成了一个非常现实的问题。比如在分布式应用系统中,由于pc拥有众多像开关量和模拟量这样的i/o接口板,因此可以用它作为工业控制现场中的下位机,完成现场数据的实时采集与相关的控制操作;而用sun工作站作为上位机,进行总的数据处理和分析。在这样的分布式应用系统中,sun工作站与pc之间的通讯便是一个十分关键的问题。

sun工作站与pc之间的通讯可分为两个方面:一是硬件连接,二是软件编程。对于硬件连接,一般说来可有以下两种作法,第一种是利用sun工作站本身的rs-232/rs-423串口与pc的rs-232串口,进行串行异步通讯。这种方法最大的优点是成本低,缺点是数据传输速度慢,数据的查错和纠错工作需由用户自己完成,另外还需对硬件直接编程。第二种方法是利用sun工作站本身配备的以太网接口,这时要求也为pc配上一块网络接口卡,两者通过同轴电缆相连,构成以太网,从而实现它们之间的通讯。这种方法的优点是数据传输速度快,非常适合对实时性要求较高的应用项目,再加上有系统软件与编程工具软件包的支持,因此编程工作相对来说也比较简单。该方法的缺点是成本比第一种方法稍高一些。

本文将着重介绍一下在第二种硬件连接方式下,即在以太网络环境中,为了实现sun工作站与pc之间的进程通讯,在软件上需要做的一些工作。

我们知道,sun工作站采用了一种称为nfs(network file system)的分布式文件系统,该系统最大的优点是独立于机型、操作系统以及网络体系结构,实现了在异构环境下的文件共享。在nfs系统的支持下,文件存取对用户透明,即用户使用网络上文件的方法与使用本地文件的方法完全一致。

为了实现pc与sun工作站之间的文件共享,我们还必须在pc上安装一套称为pc-nfs的软件,该软件由sun公司提供。在安装完该软件之后,pc的用户就可以像使用本地上的软、硬盘那样使用sun工作站上的文件了。

到此为止,由于有了sun nfs和pc-nfs这两个系统软件的相互配合,已经可以完成sun工作站与pc进程之间的通讯,其通讯方式是通过文件共享。但这种方法在实际应用中往往显得速度不够理想,而且由于需要依靠文件作媒介,因此在时间上和操作上造成的额外开销较大。于是,我们有必要探索一种sun工作站与pc之间的进程不通过文件共享,而是直接进行实时通讯的方法。作者通过一段时间的摸索与实践,找到了一种可行的方案,现提出来供大家参考。

这种实现进程间直接通讯方法的实质是在互连网域(internet domain)支持的tcp/ip协议下,进行基于socket(套接字)系统调用的程序设计。socket是网络在传输层上提供给应用程序的接口,其目的主要是用来实现网络上进程之间的通讯。下面我们就通过一个具体的实例来详细说明这一方法。

由于socket程序设计通常都使用client/server(客户/服务器)的模型,因此我们在具体实现上也遵循这一原则,把sun工作站作为server, pc作为client,两者在程序设计上分工不同。在本例中,我们要完成的任务是在工作站上的进程与在pc上的进程之间进行双向的数据传输,程序中分别各以一个字符串来代表实际要传送的信息。

由于socket程序设计是一个较为复杂的问题,因此本文不作详细论述,有关这方面的内容请读者参考相应书籍(例如sun公司的network programming等)。我们在这里只把程序中需要注意的几个问题向大家作一简要说明。

1.由于sun工作站上的进程属于server方,因此它必须首先运行,等待来自pcclient方进程的连接请求;

2.工作站上的进程运行之后,首先会在屏幕上显示一个端口(port)号。端口号是tcp/ip协议标识进程地址的一个组成部分,因此工作站上进程的端口号连同工作站的机器名称(hostname)必须要送到pc上要与之进行通讯的那个进程,只有这样,pc上的进程才知道自己将要与哪一个进程发生联系。在本文给出的实例中采用了通过命令行参数传递信息的方法,当然也可以使用其它方法;

3.在上述实例程序中,进程之间数据的传输使用了read()和write()函数,但这两个函数在用于socket时与用于文件时的实际操作并不完全一样。由于网络本身传输特性的限制,它们很可能在一次调用中不能读出或写入函数参数中要求的那么多数据量。因此为了完成类似于文件操作read()和write()函数同样的功能,我们专门编写了两个新的函数readpkt()和writepkt(),分几次读入或写出规定的字节数;

4.工作站上执行的程序只要在工作站上编译和连接后即可投入运行,而在pc上运行的程序必须要有sun公司提供的pc-nfs programer's toolkit软件包的支持,该软件包提供了与socket调用有关的所有函数。本文pc上的程序是用borland c++ 3.0编译程序编译的,此外,该软件包也支持microsoft c语言和microsoft windows下应用程序的编程。在生成可执行代码之后,即.exe文件,就不再依赖该软件包了,但仍要在pc-nfs系统支持下运行。

以上就是sun工作站与pc进程之间进行实时通讯的一种方法。当然,这里所说的“实时”也只是相对而言的,因为sunos操作系统属于unix操作系统这一大类,而unix操作系统本身是一个分时的操作系统,不可能有绝对的实时。但本文讨论的这种方法在实际项目中经过检验,已经可以满足实时性的要求,为sun工作站与pc之间进行高速的数据传输开辟了一条新路。

最后需要说明的是,本文介绍的进程之间实时通讯的方法不仅适用于sun工作站与pc之间,而且也适用于连接到该以太网络上的所有机器,其中包括sun工作站与sun工作站之间进程的通讯,pc与pc之间进程的通讯以及它们之间的任意组合。sun工作站(即server方)程序:程序文件名:sun.c

执行方法:sun

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h><br>#include <netdb.h>

#include <stdio.h>

#define data "1234567890"

main()

{

int sock,length;

struct sockaddr-in server;

int msgsock;

char buf;

int readpkt(),writepkt();

sock=socket(af-inet,sock-stream,0);

if (sock<0) {

perror("opening stream socket");

exit(1);

}

server.sin-family=af-inet;

server.sin-addr.s-addr=inaddr-any;

server.sin-port=0;

if (bind(sock,(struct sockaddr *)&server,sizeof server)<0){

perror("binding stream socket");

exit(1);

}

length=sizeof server;

if (getsockname(sock,(struct sockaddr *)&server,&length)<0){

perror("getting socket name");

exit(1);

}

printf("socket port #%d",ntohs(server.sin-port));

listen(sock,5);

msgsock=accept(sock,(struct sockaddr *)0,(int *)0);

if (msgsock==-1){

perror("accept");

exit(1);

}

else do{

bzero(buf,sizeof buf);

if (readpkt(msgsock,buf,1024)<0){

perror("reading stream message");

break;

}

prinft("%s",buf);

strcpy(buf,data);

if (writepkt(msgsock,buf,1024)<0) {

perror("writing stream message");

break;

}

}while (1);

close(msgsock);

close(sock);

return 0;

}

int readpkt(sock,buf,size)

int sock;

char *buf;

int size;

{

int rest, readnum,count;

count=0;

rest=size-count;

while (rest) {

readnum=read(sock,buf,rest);

if (readnum<0) return readnum;

rest-=readnum;

buf+=readnum;

}

return (size-rest);

}

int writepkt(sock,buf,size)

int sock;

char *buf;

int size;

{

int rest,writenum,count;

count=0;

rest=size-count;

while (rest){

writenumwrite(sock,buf,rest);

if (writenum<0) return writenum;

rest-=writenum;

buf+=writenum;

}

return (size-rest);

}

pc(即client方)程序:

程序文件名:pc.c

执行方法:pc<sun工作站名称><sun进程端口号>

#include <sys/tk-types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

#include <stdio.h>

#include <string.h>

#define data "abcdefghijklmnopqrstuvwxyz"

main(argc,argv)

int argc;

char *argv;

{

int sock;

struct sockaddr-in server;

struct hostent *hp,*gethostbyname();

char buf;

int readpkt(),writepkt();

sock=socket(pf-inet,sock-stream,0);

if (sock<0){

perror("opening stream socket");

exit(1);

}

server.sin-family=af-inet;

hp=gethostbyname(argv);

if (hp==0){

fprintf(stderr,"%s:unknown host.",argv);

exit(2);

}

memcpy((char *)&server.sin-addr,(char *)hp->h-addr,hp->h-length);

server.sin-port=htons(atoi(argv));

if (connect(sock,(struct sockaddr *)&server,sizeof server)<0){

perror("connecting stream socket");

exit(1);

}.

do {

strcpy(buf,data);

if (writepkt(sock,buf,1024)<0){

perror("writing on stream socket");

break;

}

memset(buf,0,1024);

if (readpkt(sock,buf,1024)<0){

perror("reading from stream socket");

break;

}

printf("%s",buf);

} while(1);

close(sock);

return 0;

}

int readpkt(sock,buf,size)

int sock;

char *buf;

int size;

{

int rest,readnum,count;

count=0;

rest=size-count;

while (rest) {

readnum=read(sock,buf,rest);

if (readnum<0) return readnum;

rest-=readnum;

buf+=readnum;

}

return(size-rest);

}

int writepkt(sock,buf,size)

int sock;

char *buf;

int size;

{

int rest,writenum,count;

count=0;

rest=size-count;

while (rest) {

writenum=write(sock,buf,rest);

if (writenum<0) return writenum;

rest-=writenum;

buf+=writenum;

}

return (size-rest);

上一篇:浅谈湿法磷酸中三废的综合利用 下一篇:浅谈香港地铁的有效运作