转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 数据库 >> MySql >> 正文
Linux网络编程,第一部分:BSD套接口篇(上)         ★★★★

Linux网络编程,第一部分:BSD套接口篇(上)

作者:闵涛 文章来源:闵涛的学习笔记 点击数:1863 更新时间:2009/4/22 20:45:43

翻译前言:

    本文选自Linux Journal 的一篇系列文章Linux Network Programming,并作了部分修改。你可能会说网上关于套接口编程的文章一大堆,但是这是我的第一篇译作,对我来说这是一次新的尝试,有什么意见或建议欢迎与我联系:hellwolf_ok@sina.com

 

Linux网络编程,第一部分
BSD套接口篇
    ——这是关于如何用各种可以得到的接口为Linux开发网络程序的系列文章的第一篇。就像大多数Unix-based的操作系统一样,Linux支持将TCP/IP作为本地的网络传输协议。在这个系列中,我们假定你已经比较熟悉Linux上的C编程和Linux的一些系统知识诸如signals,forking等等。
    这篇文章是关于如何用BSD套接口创建网络程序的基础介绍 。在下一篇中,我们会解决涉及到建立(网络)deamon进程的问题。而且今后的文章我们还会涉及到使用远程过程调用(RPC),以及用CORBA/distributed objects进行开发。

 

一、TCP/IP的基础介绍
    TCP/IP协议族允许两个运行在同一台电脑或者由网络连接在一起的两台电脑上的程序进行通讯。这个协议族是专门为了在不可靠的网络上进行通讯设计的。TCP/IP允许两个基本的操作模式——面向连接的可靠的传输(指TCP)和无连接的(connectionless)不可靠的传输(UDP)。下图举例说明了TCP/IP协议族的分层结构。

tcpip协议族


    TCP提供带有对上层协议透明的中继功能的,顺序的,可靠的,双向的(bi-directional),以连接为基础的字节传输流。TCP将你的信息分割成数据报(不大于64kb)并保证所有的数据报无误的按照顺序都到达目的地。由于以连接为基础,所以一个虚拟连接必须在一个网络实体(network entity)和另一个之间进行通信前建立。UDP相反则提供一个(非常快的)无连接的不可靠消息传输(消息的大小是一个确定的最大长度)。
    为了使程序间可以相互通信,不论他们是在同一个机器(通过loopback接口)还是不同主机,每一个程序都必须有独立的地址。
    TCP/IP地址由两部分组成——用来辨别机器的IP地址和用来辨别在那台机器上的特定程序的端口地址。
    地址可以是点分(dotted-quad)符号形式的(如,127.0.0.1)或者是主机名形式的(如,www.csdn.net)。系统可以使用/etc/hosts或DNS域名服务(如果可以获得的话)进行主机名到点分符号地址(也就是IP地址)的转换。
    端口从1号开始编号。1和IPP0RT_RESERVED(在/usr/include/netinet/in.h中定义,通常为1024)之间的段口号保留给系统使用(也就是说,你必须以root的身份建立一个网络服务来绑定这部分的端口)。
    最简单的网络程序大都用的客户-服务器模型。一个服务进程等待一个客户进程连接他。当连接建立时,服务器代表客户执行特定的任务,通常这这以后连接就中断了。

二、使用BSD套接口界面
    最通行的TCP/IP编程方法就是使用BSD套接口界面编程。通过它,网络端点(network endpoints)(IP地址和端口地址)以套接口(sockets)的形式出现。
    这套套接口IPC(interprocess communication,进程间通讯)设施(从4.2BSD开始引入)的设计是为了能让网络程序的设计能够独立于不同的底层通信设施。
1、建立一个服务器程序
    要使用BSD界面建立一个服务器程序,你必须通过以下步骤:
      1。通过函数socket()建立一个套接口
      2。通过函数bind()绑定一个地址(IP地址和端口地址)。这一步确定了服务器的位置,使客户端知道如何访问。
      3。通过函数listem()监听(listen)端口的新的连接请求。
      4。通过函数accept()接受新的连接。
    通常,维护代表了客户的请求可能需要花费相当长的一段时间。在处理一个请求时,接收和处理新的请求也应该是高效的。达到这种目的的最通常的做法是让服务器通过fork()函数拷贝一份自己的进程来接受新的连接。(下图:客户服务器代码模型的表示形式)

客户服务器代码模型


    以下的例子显示了服务器是如何用C实现的:
/*
 * Simple "Hello, World!" server
 * Ivan Griffin (ivan.griffin@ul.ie)
 */

/* Hellwolf Misty translated */

#include  /* */
#include  /* exit() */
#include  /* memset(), memcpy() */
#include  /* uname() */
#include
#include    /* socket(), bind(),
                             listen(), accept() */
#include
#include
#include
#include  /* fork(), write(), close() */


/*
 * constants
 */
const char MESSAGE[] = "Hello, World!\n";
const int BACK_LOG = 5;

/*
 *程序需要一个命令行参数:需要绑定的端口号
 */
int main(int argc, char *argv[])
{
    int serverSocket = 0,
        on = 0,
        port = 0,
        status = 0,
        childPid = 0;
    struct hostent *hostPtr = NULL;
    char   hostname[80] = "";
    struct sockaddr_in serverName = { 0 };

    if (2 != argc)
    {
        fprintf(stderr, "Usage: %s \n",
  argv[0]);
        exit(1);
    }
    port = atoi(argv[1]);
/ *
  *socket()系统调用,带有三个参数:
  *        1、参数domain指明通信域,如PF_UNIX(unix域),PF_INET(IPv4),
  *           PF_INET6(IPv6)等
  *        2、type指明通信类型,最常用的如SOCK_STREAM(面向连接可靠方式, 
  *           比如TCP)、SOCK_DGRAM(非面向连接的非可靠方式,比如UDP)等。
  *        3、参数protocol指定需要使用的协议。虽然可以对同一个协议
  *           家族(protocol family)(或者说通信域(domain))指定不同的协议
  *           参数,但是通常只有一个。对于TCP参数可指定为IPPROTO_TCP,对于
  *           UDP可以用IPPROTO_UDP。你不必显式制定这个参数,使用0则根据前
  *           两个参数使用默认的协议。    
  */ 
    serverSocket = socket(PF_INET, SOCK_STREAM,
  IPPROTO_TCP);
    if (-1 == serverSocket)
    {
        perror("socket()");
        exit(1);
    }
  
    /*
     * 一旦套接口被建立,它的运作机制可以通过套接口选项(socket option)进行修改。      
     */

    /*
     * SO_REUSEADDR选项的设置将套接口设置成重新使用旧的地址(IP地址加端口号)而不等待
     * 注意:在Linux系统中,如果一个socket绑定了某个端口,该socket正常关闭或程序退出后,
     * 在一段时间内该端口依然保持被绑定的状态,其他程序(或者重新启动  的原程序)无法绑定该端口。
     *
     * 下面的调用中:SOL_SOCKET代表对SOCKET层进行操作
     */
    on = 1;

    status = setsockopt(serverSocket, SOL_SOCKET,
  SO_REUSEADDR,
        (const char *) &on, sizeof(on));

    if (-1 == status)
    {
        perror("setsockopt(...,SO_REUSEADDR,...)");
    }

    /* 当连接中断时,需要延迟关闭(linger)以保证所有数据都
     * 被传输,所以需要打开SO_LINGER这个选项
     * linger的结构在/usr/include/linux/socket.h中定义:
     *   struct linger
     *   {
     *     int l_onoff;   /* Linger active */
     *     int l_linger;  /* How long to linger */
     *   };
     *   如果l_onoff为0,则延迟关闭特性就被取消。如果非零,则允许套接口延迟关闭。
     *   l_linger字段则指明延迟关闭的时间
     */

    {
        struct linger linger = { 0 };

        linger.l_onoff = 1;
        linger.l_linger = 30;
        status = setsockopt(serverSocket,
  SOL_SOCKET, SO_LINGER,
  (const char *) &linger,
  sizeof(linger));

        if (-1 == status)
        {
            perror("setsockopt(...,SO_LINGER,...)");
        }
    }

    /*
     * find out who I am
     */

    status = gethostname(hostname,
  sizeof(hostname));
    if (-1 == status)
    {
        perror("gethostname()");
        exit(1);
    }

    hostPtr = gethostbyname(hostname);
    if (NULL == hostPtr)
    {
&nb

[1] [2]  下一页


[C语言系列]C#网络编程客户端程序实现源码分享  [Web开发]JavaScript 面向对象编程, 第一部分: 继承
[MySql]值得关注的MySQL 4.1.1进展 (第一部分)  [MySql]Linux网络编程,第一部分:BSD套接口篇(下)(翻译)
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · Sql Server  · MySql
    · Access  · ORACLE
    · SyBase  · 其他
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台