1、 UNIX网络编程入门Unix是计算机使用的主流操作系统之一,TCP/IP 是广为应用的互连网协议,Unix 为 TCP/I P网络编程提供了一种网络进程通信机制:套接字接口(Sockets Interface)。本文将介绍 Un ix环境下套接字的基本概念及编程技术,并结合实例说明在 Unix下如何用套接字实现客户机/服务器方式的进程通信。一、套接字简介套接字(Socket)是网络通信的基本操作单元,它提供了不同主机间进程双向通信的端点,这些进程在通信前各自建立一个 Socket,并通过对 Socket的读/写操作实现网络通信功能。套接字分为以下 3种类型。1.字节流套接字这是最常用的套接字
2、类型,TCP/IP 协议簇中的 TCP(Transport Control Protocol)协议使用此类接口,它提供面向连接的(建立虚电路)、无差错的、发送先后顺序一致的、包长度不限和非重复的网络信包传输。2.数据报套接字TCP/IP协议族中的 UDP(User Datagram Protocol)协议使用此类接口,它是无连接的服务,以独立的信包进行网络传输,信包最大长度为 32KB,传输不保证顺序性、可靠性和无重复性,它通常用于单个报文 传输或可靠性不重要的场合。3.原始数据报套接字提供对网络下层通讯协议(如 IP协议)的直接访问,它一般不是提供给普通用户的,主要用于开发新的协议或用于提取
3、协议较隐蔽的功能。二、套接字系统调用附表是 Unix中套接字系统调用的简单说明。附表三、套接字编程方法这里将分别介绍面向连接协议的字节流套接字与非连接协议的数据报套接字的编程方法,因原始数据报套接字在实际工作中使用较少,在此不作讨论。不论何种套接字编程均采用客户机/服务器的协作模式,即由客户进程向服务器进程发出请求,服务器进程执行被请求的任务并将结果返回给客户进程。字节流套接字的服务进程和客户进程在通信前必须建立连接。建立连接及通信的步骤见图 1。1.服务进程首先调用 Socket()创建一个字节流套接字,并调用 bind()将服务器地址捆扎在该套接字上,接着调用 listen()监听连接请求
4、 ,随后调用 accept()做好与客户进程建立连接的准备,无连接请求时,服务进程被阻塞;2.客户进程调用 Socket()创建字节流套接字,然后调用 connect()向服务进程发出连接请求;3.当连接请求到来后,服务进程被唤醒,生成一个新的字节流套接字,并用新套接字同客户进程的套接字建立连接,而服务进程最早生成的套接字则继续用于监听网络上的服务请求4.服务进程和客户进程通过调用 read()和 write()交换数据;5.服务进程和客户进程通过调用 close()撤消套接字并中断连接。图 1 面向连接协议的字节流套接字系统调用图 2 非连接协议的报套接字系统调用数据套接字的服务进程客户进程
5、通信前不必建立连接, 通信的步骤见图 2。1.服务进程首先调用 Socket()创建一个数据套接字,并调用 bind()将服务器地址捆扎在该套接字上,然后调用 recvfrom()等待客户进程发来的请求;2.客户进程在调用 Socket()创建一个数据报套接字后,调用 bind()将客户机地址捆扎在此套接字上,接着调用 sendto()向服务进程发送请求,然后调用 recvfrom()等待服务进程返回该请求的处理结果; 3.服务进程在执行客户进程所请求的任务后,调用 sendto()将处理结果返回给客户进程4.服务进程和客户进程通过调用 close()撤消套接字。 UNIX网络编程入门之二UN
6、IX 网络编程入门四、套接字编程示例下面给出一个运用字节流套接字在 TCP/IP网络上实现客户机/服务器方式进程通信的实例。在此例中,服务进程先于客户进程运行,当双方建立连接后,服务进程通过该连接向客户进程不断发送一个连续增长的序列数,客户进程每接收到 50个序列数就在屏幕上显示一个.,显示至 20个点后换行,直至任意一方进程被中断为止。/*server.c*/# include # include # include # include # include main()int sock,namelen,seq,netint;struct sockaddr-in server;/存服务器的 i
7、nternet地址 char msgsock;char buf1024;/创建 internet域的 TCP协议的字节流套接字sock=socket(AF-INET,SOCK-STREAM,IPPROTO-TCP);if(sock# include # include # include # include main(argc,argv)int argc;char *argv;int sock,myseq,recvseq;struct sockaddr-in server;/存服务器的 internet地址struct hostcnt *h;/存主机信息/命令行必须跟参数:服务器的主机名,该主
8、机/必须在/etc/hosts 文件中定义,例如:/ 192.7.100.31 hp486if(argc!=2)printf(“Usage:%s servernamen“,argv0;exit(1);/创建 internet域 TCP协议的字节流套接字sock=socket(AF-INET,SOCK-STREAM,IPPROTO-TCP);if(sockh-addr,server.sinport=htons(1032); /填入公认的服务端口号与服务进程建立连接if(connect(sock,int clilen;struct sockaddr_in cli_addr, serv_addr;c
9、har info100;int infolen;int rc;if (sockfd = socket(AF_INET, SOCK_STREAM, 0) = 10 )exit(-1);/*此时连接已建立, 可通过对套接字的读写实现通信*/memset(printf(“enter account no:“);scanf(“%s“,data.accno); /*输入要检索的帐号*/infolen=sizeof(data.accno);bcopy(if ( (rc=TCPSEND(sockfd, info, infolen) = -1 )fprintf(stderr, “TCPSend failed
10、!n“);/*客户进程向服务进程发送帐号信息*/infolen=sizeof(info);if ( (rc=TCPRECEIVE(sockfd, info, infolen) = -1 ) fprintf(stderr, “TCPRecv failed !n“);/*客户进程接收服务进程返回的帐户信息*/sscanf(info,“%|%|%lf“,data.accno,data.name, /*格式转换*/if (!memcmp(data.accno,“000000“,6)/*判断是否查到*/printf(“There is no such account in server database
11、.n“);else /*显示帐户信息*/printf(“accno is %sn“,data.accno);printf(“name is %sn“,data.name);printf(“amount is %-10.2lfn“,data.amt);shutdown(sockfd, 2);close(sockfd);/*公共程序:tcpipop.c*/* Using TCP/IP Protocol.*/#include #include #include #include #include extern int TCPSEND(int fd, char *buf, int len)int i=0;int send_rc;for ( ; i= 10 )return(-1);elsereturn(send_rc);extern int TCPRECEIVE(int fd, char *buf, int len)int i=0;int receive_rc;for ( ; i= 10 )return(-1);elsereturn(receive_rc);