Linux c socket编程

当前位置:  编程语言> c/c++

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

 
分享到: 2
    发布时间: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函数

函数原型:  

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

功能说明

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

参数说明:

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

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

  protocol通常赋值"0"。

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

2)bind函数

函数原型:    

1
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函数

函数原型:    

1
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函数

函数原型:  

1
int listen( int sock_fd, int backlog);

功能说明:

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

参数说明:

  sock_fd 是socket()函数返回值;

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

5)accecpt函数

函数原型:  

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

功能说明:

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

参数说明:

  sock_fd是被监听的socket描述符,

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

  addrlen是结构sockaddr_in的长度。

6)write函数

函数原型:  

1
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函数

函数原型:  

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

函数说明:

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

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

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

8)close函数

函数原型:

1
int close(sock_fd);

说明:

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

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

2 socket编程其他函数说明

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

(1) 网络字节顺序

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

(2) 有关的转换函数

1
2
3
4
5
6
7
8
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地址的字符串转换成一个无符号长整型,如:

1
2
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) 客户端源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#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)服务端源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#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)如何在linux下上网?
在Linux下开发手机客户端或Pc客户端交互的服务器,需要学哪些知识?
linux端是服务器,客户端连接后,有时并不知道客户端断开,怎么侦测?
linux 能ping通客户端ip,但ping不通客户端的域名。
Linux网络编程(怎样实现两个客户端之间的通信)
Linux的BBS客户端 QTerm
Linux的博客客户端 Drivel
Linux 代理 一个客户端来就创建一个连接
linux客户端如何配置网络?
linux socket多客户端程序
linux下用kerberos客户端加入windows域的问题
求助:Linux下ftp客户端代码编写
linux怎样装那个锐杰认证客户端
Linux系统做服务器,客户端可使用windows系列的系统吗
Linux下默认的邮件客户端是什么
linux作为客户端,跟windows通信,如何保持一直在线?
linux中监听客户端访问tomcat的命令
Linux的Twitter客户端 Twitux
Linux邮件客户端 Evolution
linux下的写的tcp客户端,connect到windows的服务器超时
Linux下c/c++ boost安装及并发编程库mpi介绍
都说《UNIX环境高级编程》好,对于学linux编程好不好?《Linux下的c编程》《嵌入式系统C编程》那个更适合初学者?各是那个出版社的?(
我想学Linux编程,请大家推荐几本学习Linux下C/C++编程的书
学Linux编程前要学Unix吗?哪里有学Linux编程的好书下载?
我想学习linux桌面编程,那么有没有必要学习linux的内核以及内核的相关编程呢?
linux下编程跟平时的编程有什么区别吗?
unix编程与linux编程有什么区别?
Linux下的编程指的就是Shell编程吗?
帮我介绍基本linux下编程的书,《Linux上的C编程》这本书怎么样?还有别的书吗?
Linux下使用openssl api编程socket编程,为什么要编译啊?
请教linux下的编程的选择:我听说有gtk+gnome的编程,也有kde里的 什么编程,到底应该选择哪个呢?好象一个是技术好一点,一个是市场占有
相关文章推荐:
用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服务器支持客户端修改密码。。。

转载于:https://www.cnblogs.com/xjyxp/p/11145841.html

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值