EXIT_POINT:
if (error != EXT_NO_ERROR) { if (msgFd != INVALID_SOCKET) { close(msgFd); }
UD->msgFd = INVALID_SOCKET; } else {
UD->msgFd = msgFd;
if(msgFd !=INVALID_SOCKET)
printf(\ socket!\\n\
}
return(error); }
/* Function: main * * Abstract: * */
int main(int argc, const char *argv[]) {
int error;
const char *option=argv[1];
CD=(ConnectData *)malloc(sizeof(ConnectData)); memset(CD,0,sizeof(ConnectData)); if (strcmp(option, \ else
CD->waitForStart=0; ModeInit();
while((CD->waitForStart)&&(connectionMade==0)) {
error=OpenConnection(CD); }
init_sigaction(); init_time(2.0); while (1);
if(error) exit(EXIT_FAILURE); CD->waitForStart=1;
return(EXIT_SUCCESS);
} /* end main */
下面就结合本例,介绍如何在linux(uClinux)下建立通信双方中服务器端的程序。
本例是一个服务器程序,采用流式套接字,因为流式套接字提供了一种可靠的面向连接的数据传输方法。正如它的名字所指的那样,不管是对单个的数据报,还是对于数据包,流式套接字都提供一种流式数据传输。流式套接字由socket()函数调用来创建,而且调用时必须用bind()函数为它分配一个地址。
在创建好一个套接字,并赋给它一个地址之后,需要用一种方法来建立和客户机的连接,为了做到这一点,要使用listen()函数。该函数告诉套接字开始侦听客户机的连接请求。一旦将套接字设置成侦听连接后,实际的连接就可以由accept()函数来完成。如果连接成功的接受,accept()函数将返回一个新套接字的描述符,正是由accept()函数所创建的这个新套接字会被用作以后处理新的连接。在该例程中,ConnectData结构体中的msgFd套接字就是用来真正和客户端进行通信的socket。
原来的侦听套接字将会继续侦听新的连接请求,而新的请求可能会通过accept()函数的再一次调用而获得接受。
到目前为止,读者已经看到有两类套接字了,一个是由socket()函数创建的,称之为“侦听套接字”(listening socket),另一类是由accept()函数创建的,称之为“连接套接字”(connected socket),它们的区别如表7.1所示。
表7.1 两种套接字比较
创建 应用 侦听套接字 socket() bind(),listen(),accept() 连接套接字 accept() 文件读写调用read(),write() 网络文件专用函数send(),recv() 作用 监听来自客户端的连接请求,并建立连接 生存周期 一个服务器进程与一个监听套接字相对应,与服务器进程同时存在或消灭 与某一个客户进程连接,完成具体的数据传输工作 一次连接对应一个连接套接字,建立连接时创建套接字,连接结束时关闭
在主程序中,利用信号处理函数,进行每隔2秒定时的往客户端发送字符串(有关信号处理函数的知识,在本节开始已有介绍)。
网络应用程序包括两个部分:一部分是服务器端的应用程序,主要是用于接受客户端的连接请求,接收客户端的信息,处理客户端的计算请求,向客户端发送计算结果和应答信息等。另一部分就是客户端应用程序,主要用于申请连接到服务器,向服务器发送计算请求,处理服务器发回的计算结果和其他信息。
本书所给的例子只是服务器端的应用程序,对于客户端程序,在此只为读者做一个简单的介绍。
在客户端的应用程序为了让服务器接收一个连接请求,必须首先也要建立一个socket,一般也是使用流式套接字,接着发起一个请求,通过调用函数connect()来实现。
一旦客户机套接字和服务器套接字建立了连接,双方就可以通过send()和recv()函数的调用来发送和接收数据了。 流式套接字基本使用方法如图7.9所示。
图7.9 流式套接字用法
如果想断开连接,调用函数close()真正释放和套接字相关的系统资源。 7.4 .3 添加用户应用程序到uClinux
以下通过一个具体实例向读者介绍将程序添加到uClinux的标准方法。 例如要把前面提到的源程序lednxy.c添加到运行于目标板上的uClinux操作系统中,则该文件应在目录/home/nie/uClinux-Samsung/user下,进入uClinux-Samsung/user目录并建立一个自己的子目录,比如键入: mkdir myapp,
这样在user目录下就建立了一个新的子目录myapp,把lednxy.c拷贝到myapp目录下,并将该源文件相应的makefile文件也拷贝到该目录下。注意,为了使用标准方法,我们应该修改一下刚才的makefile文件,这个文件名应为Makefile,写成这样的形式:
EXEC = lednxy OBJS = lednxy.o all: $(EXEC) $(EXEC): $(OBJS)
$(CC) $(LDFLAGS) –o $@ $(OBJS) $(LDLIBS) romfs:
$(ROMFSINST) /bin/$(EXEC) clean:
rm –f $(EXEC) *.elf *.gdb *.o
进入user目录,增加一行语句到该目录下的Makefile文件中,
dir_$(CONFIG_USER_MYAPP_LEDNXY) += myapp
该语句的作用是让编译器可以访问到我们所创建的myapp目录下的makefile文件,保存后退出。
切换到目录/home/nie/uClinux-Samsung/config下,编辑Configure.help文件,即输入一下命令
cd ../config vi Configure.help
这是一个包含了在配置的时候出现的所有文本信息的文件。在这个文件