扩展阅读
  • linux c/c++ IP字符串转换成可比较大小的数字
  • 在win分区上安装linux和独立分区安装linux有什么区别?可以同时安装吗?(两个linux系统)
  • linux哪个版本好?linux操作系统版本详细介绍及选择方案推荐
  • 在虚拟机上安装的linux上,能像真的linux系统一样开发linux程序么?
  • secureCRT下Linux终端汉字乱码解决方法
  • 我重装window后,把linux的引导区覆盖了,进不了linux怎么办?急啊,望热心的人帮助 (现在有linux的盘)
  • Linux c字符串中不可打印字符转换成16进制
  • 红旗Linux主机可以通过127.0.0.1访问,但如何是连网的Win2000机器通过Linux的IP去访问Linux
  • Linux常用命令介绍:更改所属用户群组或档案属性
  • 安装vmware软件,不用再安装linux系统,就可以模拟linux系统了,然后可以在其上学习一下LINUX下的基本操作 了?
  • linux命令大全详细分类介绍及常用linux命令文档手册下载
  • 我重装window后,把linux的引导区覆盖了,进不了linux怎么办?急啊,望热心的人帮助 (现在没有linux的盘,只有DOS启动盘)
  • Linux Kernel 'sctp_v6_xmit()'函数信息泄露漏洞
  • 如何让win2000和linux共存。我装好WIN2000,再装LINUX7.0,但LILO只能找到LINUX,不能引导WIN2000
  • linux c下利用srand和rand函数生成随机字符串
  • 在windows中的VMware装了个linux,主板有两个串口,能做windows和linux的串口通信测试么,怎么测试这两个串口在linux是有效
  • Linux c++虚函数(virtual function)简单用法示例代码
  • 我们网站的服务器从windows2000迁往linux,ASP程序继续使用,可是我连LINUX的皮毛都不了解,大家告诉我LINUX下怎么建网站??
  • Docker官方镜像将会使用Alpine Linux替换Ubuntu
  • 中文Linux与西文Linus分别哪一个版是权威?I认为是:中科软的白旗Linux与西文的绿帽子Linux!大家的看法呢?
  • Linux下chmod命令详细介绍及用法举例
  • Windows2000和Linux双操作系统,Linux系统有问题,我直接把Linux分区删除后,Windows2000进不去了,怎么办???
  •  
    当前位置:  编程语言>c/c++

    Linux c socket编程:简单的客户端(client)和服务端(server)实现

     
        发布时间:2013-8-13  


        本文导语: 1 基本socket函数 Linux系统是通过提供套接字(socket)来进行网络编程的。网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符。socket也有一个类似于打开文件的函数:socket(),调用socket(),该函数返回一个整型的socket...

    1 基本socket函数

       Linux系统是通过提供套接字(socket)来进行网络编程的。网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符。socket也有一个类似于打

    文件的函数:socket(),调用socket(),该函数返回一个整型的socket的描述符,随后的连接建立、数据传输等操作也都是通过该socket实现。

    1)socket函数

    函数原型:  

    int socket(int domain, int type, int protocol);

    功能说明

      调用成功,返回socket文件描述符;失败,返回-1,并设置errno

    参数说明:

      domain指明所使用的协议族,通常为PF_INET,表示TCP/IP协议;

      type参数指定socket的类型,基本上有三种:数据流套接字、数据报套接字、原始套接字

      protocol通常赋值"0"。

      两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。socket数据结构中包含这五种信息。

    2)bind函数

    函数原型:    

    int bind(int sock_fd,struct sockaddr_in *my_addr, int addrlen);

    功能说明:

      将套接字和指定的端口相连。成功返回0,否则,返回-1,并置errno.

    参数说明:

          sock_fd是调用socket函数返回值,

      my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针

      struct sockaddr_in结构类型是用来保存socket信息的:

      struct sockaddr_in {

      short int sin_family;

      unsigned short int sin_port;

      struct in_addr sin_addr;

      unsigned char sin_zero[8];

      };

       addrlen为sockaddr的长度

    3)connect函数

    函数原型:    

    int connect(int sock_fd, struct sockaddr *serv_addr,int addrlen);

    功能说明:

      客户端发送服务请求。成功返回0,否则返回-1,并置errno。

    参数说明:

      sock_fd 是socket函数返回的socket描述符;serv_addr是包含远端主机IP地址和端口号的指针;addrlen是结构sockaddr_in的长度。

    4)listen函数

    函数原型:  

    int listen(int sock_fd, int backlog);

    功能说明:

      等待指定的端口的出现客户端连接。调用成功返回0,否则,返回-1,并置errno.

    参数说明:

      sock_fd 是socket()函数返回值;

      backlog指定在请求队列中允许的最大请求数

    5)accecpt函数

    函数原型:  

    int accept(int sock_fd, struct sockadd_in* addr, int addrlen);

    功能说明:

      用于接受客户端的服务请求,成功返回新的套接字描述符,失败返回-1,并置errno。

    参数说明:

      sock_fd是被监听的socket描述符,

      addr通常是一个指向sockaddr_in变量的指针,

      addrlen是结构sockaddr_in的长度。

    6)write函数

    函数原型:  

    ssize_t write(int fd,const void *buf,size_t nbytes)

    功能说明:

       write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数.失败时返回-1. 并设置errno变量.

       在网络程序中,当我们向套接字文件描述符写时有俩种可能:

         (1)write的返回值大于0,表示写了部分或者是全部的数据.

         (2)返回的值小于0,此时出现了错误.需要根据错误类型来处理.

        如果错误为EINTR表示在写的时候出现了中断错误.

         如果错误为EPIPE表示网络连接出现了问题.

    7)read函数

    函数原型:  

    ssize_t read(int fd,void *buf,size_t nbyte)

    函数说明:

       read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0 表示已经读到文件的结束了,小于0表示出现了错误.

       如果错误为EINTR说明读是由中断引起的,

       如果错误是ECONNREST表示网络连接出了问题.

    8)close函数

    函数原型:

    int close(sock_fd);

    说明:

    当所有的数据操作结束以后,你可以调用close()函数来释放该socket,从而停止在该socket上的任何数据操作:

    函数运行成功返回0,否则返回-1

    2 socket编程其他函数说明

    1) 网络字节顺序及其转换函数

    (1) 网络字节顺序

    每一台机器内部对变量的字节存储顺序不同,而网络传输的数据是一定要统一顺序的。所以对内部字节表示顺序与网络字节顺序不同的机器,一定要对数据进行转换,从程序的可移植性要求来讲,就算本机的内部字节表示顺序与网络字节顺序相同也应该在传输数据以前先调用数据转换函数,以便程序移植其它机器上后能正确执行。真正转换还是不转换是由系统函数自己来决定的。

    (2) 有关的转换函数

    unsigned short int htons(unsigned short int hostshort):
    //主机字节顺序转换成网络字节顺序,对无符号短型进行操作4bytes
     unsigned long int htonl(unsigned long int hostlong):
    //主机字节顺序转换成网络字节顺序,对无符号长型进行操作8bytes
     unsigned short int ntohs(unsigned short int netshort):
    //网络字节顺序转换成主机字节顺序,对无符号短型进行操作4bytes
     unsigned long int ntohl(unsigned long int netlong):
    //网络字节顺序转换成主机字节顺序,对无符号长型进行操作8bytes

    注:以上函数原型定义在netinet/in.h里

    2)IP地址转换

    有三个函数将数字点形式表示的字符串IP地址与32位网络字节顺序的二进制形式的IP地址进行转换

    (1) unsigned long int inet_addr(const char * cp):该函数把一个用数字和点表示的IP地址的字符串转换成一个无符号长整型,如:

    struct sockaddr_in ina;
    ina.sin_addr.s_addr=inet_addr("222.216.117.11");

    该函数成功时:返回转换结果;失败时返回常量INADDR_NONE,该常量=-1,二进制的无符号整数-1相当于255.255.255.255,这是一个广播地址,所以在程序中调用iner_addr()时,一定要人为地对调用失败进行处理。由于该函数不能处理广播地址,所以在程序中应该使用函数inet_aton()。

    (2)int inet_aton(const char * cp,struct in_addr * inp):此函数将字符串形式的IP地址转换成二进制形式的IP地址;成功时返回1,否则返回0,转换后的IP地址存储在参数inp中。

    (3) char * inet_ntoa(struct in-addr in):将32位二进制形式的ip地址转换为数字点形式的ip地址,结果在函数返回值中返回,返回的是一个指向字符串的指针。

    3)字节处理函数

    Socket地址是多字节数据,不是以空字符结尾的,这和C语言中的字符串是不同的。Linux提供了两组函数来处理多字节数据,一组以b(byte)开头,是和BSD系统兼容的函数,另一组以mem(内存)开头,是ANSI C提供的函数。

    以b开头的函数有:

    (1) void bzero(void * s,int n):将参数s指定的内存的n个字节设置为0,通常它用来将套接字地址清0。

    (2) void bcopy(const void * src,void * dest,int n):从参数src指定的内存区域拷贝指定数目的字节内容到参数dest指定的内存区域。

    3 简单的客户端(client)和服务端(server)实现源码

    1) 客户端源码:

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <ctype.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <errno.h>
    // gcc -g -o simple_client simple_client.c
    int main(int argc,char *argv[])
    {
        char ip[20]={"192.168.10.23"};
        int port=10000;
        int server_fd;
        struct sockaddr_in server_listen_addr;
        bzero(&server_listen_addr,sizeof(server_listen_addr));
        server_listen_addr.sin_family=AF_INET;
        server_listen_addr.sin_port=htons(port);
        inet_pton(AF_INET,"192.168.10.23",(void*)&server_listen_addr.sin_addr);
       // inet_aton(ip,&server_listen_addr.sin_addr);
       // bzero(&(server_listen_addr.sin_zero),8);
        server_fd=socket(AF_INET,SOCK_STREAM,0);
        int ret=connect(server_fd,(const struct sockaddr *)&server_listen_addr,
                        sizeof(struct sockaddr));      
         printf("server_fd=[%d] ret=[%d]n",server_fd,ret);
         if(ret<0)
         { 
          perror("error: socket connect!");        
          exit(1);
         }
         char data[20]={"good luck!n"};
         int num=send(server_fd,(void*)data,strlen(data),0);
         printf("send bytes[%d][%s]n",num,data);
         close(server_fd);
        return 1;
    }

    2)服务端源码:

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <ctype.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <errno.h>
    //gcc -g -o simple_server simple_server.c
    int main(int argc,char *argv[])
    {
        int port=10000;
        int server_listen_fd;
        int server_accept_fd;
        struct sockaddr_in server_listen_addr;
        struct sockaddr_in server_accept_addr;
        bzero(&server_listen_addr,sizeof(server_listen_addr));
        bzero(&server_accept_addr,sizeof(server_accept_addr));
        server_listen_addr.sin_family=AF_INET;  
        server_listen_addr.sin_addr.s_addr=INADDR_ANY;
        server_listen_addr.sin_port=htons(port);
        server_listen_fd=socket(AF_INET,SOCK_STREAM,0);
        if(-1==server_listen_fd)
         {
           perror("fail to create socket!");
           exit(1);
         }
        if(bind(server_listen_fd,(struct sockaddr*)&server_listen_addr,
                sizeof(server_listen_addr))==-1)
          {
            perror("can't to bind");
            exit(1);
          }
         if(listen(server_listen_fd,10)==-1)
          {
            perror("can't to bind");
            exit(1);
          }
          while(1)
            {  
              int size=sizeof(server_accept_addr);
              printf("server socket begin accept:n");
              server_accept_fd=accept(server_listen_fd,(struct sockaddr*)&server_accept_addr,&size);
              printf("accept con_fd=%dn",con_fd);
              if(server_accept_fd<0)
              {            
                  perror("error:socket accept!exited!n");            
                  exit(1);            
              }
              int num=0;
              char data[200]={0};      
              int ret=read(server_accept_fd,(void*)data,199);        
              close(server_accept_fd);
              printf("DATA:[%s]n",data);
            }
        return 1;
    }

    以上代码均在CentOS 5.4上编译调试通过。


    相关文章推荐:
  • 用LINUX做HELIX服务器,用W2K做客户机,客户机视频点播,连接时出现问题!!!!
  • 在单位用windows客户机可在ie设置代理上网,但linux客户机不行
  • 关于linux socket 客户端编程
  • 关于linux环境下服务器 是如何获取客户端的相关硬件信息
  • linux能否成为动态域名解析客户端的动态域名解析服务器?
  • 客户端是linux通过socket编程实现服务器端win平台接收?
  • 请问有没有Linux下SOCKET服务端和客户端的接口函数!!
  • linux客户端能不能使用x界面呀
  • 高分请教:如何在linux上建vpn的客户端!
  • 客户端访问Linux作为服务器的网站,flash无法显示。
  • 哪里有中兴认证客户端linux版本下载?
  • 大侠,求助!!LINUX下TCP套接字编程中客户端出现段错误
  • 如何在远程linux客户端上运行gui程序
  • 虾米电台Linux客户端 xmradio
  • 百度云linux客户端
  • 锐捷认证Linux客户端 RuijieClient
  • 求FTP客户端源程序或相关资料(C,LINUX )
  • ~~双网卡WinXP设置为共享上网,为什么Linux客户机不能上网~~
  • 如何使用LINUX为不同子网的WIN98客户端不同的应用程序做代理?给分100
  • Linux 下有没有FTP服务器支持客户端修改密码。。。


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3