从一个简单的使用TCP例子开始socket编程,其基本步骤如下:

server                                                  client

+++++++                                          ++++++++

创建socket                                          创建socket

+++++++                                          ++++++++

|                                                         |

|                                                         |

|                                                         |

+++++++                                          ++++++++

地址赋值(                                           地址赋值(

自己的地址)                                        服务器地址)

+++++++                                          ++++++++

|                                                         |

|                                                         |

|                                                         |

++++++++                                              |

用bind绑定                                                |

socket和地址                                             |

++++++++                                              |

|                                                         |

|                                                         |

|                                                         |

+++++++                                                 |

listen                                                         |

+++++++                                                  |

|                                                    ++++++++++

|   <------------------------------          connect 服务器

|                                                    ++++++++++

+++++++                                                  |

accept                                                        |

+++++++                                                  |

|                                                           |

|                                                    +++++++++

|                                                     recv 和send

|                                                     进行数据处理

|                                                     +++++++++

+++++++++                                                |

用accept得到                                                 |

的socket进行                                                 |

recv 和 send                                                 |

+++++++++                                                |

|                                                             |

|                                                             |

|                                                             |

+++++++++                                        +++++++++

close socket                                         close socket

+++++++++                                        +++++++++

根据以上步骤,服务器端的代码为

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <stdlib.h>
  6. #include <syslog.h>
  7. #include <errno.h>
  8. #define MAX_LISTEN_NUM 5
  9. #define SEND_BUF_SIZE 100
  10. #define RECV_BUF_SIZE 100
  11. #define LISTEN_PORT 1010
  12. int main()
  13. {
  14. int listen_sock = ;
  15. int app_sock = ;
  16. struct sockaddr_in hostaddr;
  17. struct sockaddr_in clientaddr;
  18. int socklen = sizeof(clientaddr);
  19. char sendbuf[SEND_BUF_SIZE] = {};
  20. char recvbuf[RECV_BUF_SIZE] = {};
  21. int sendlen = ;
  22. int recvlen = ;
  23. int retlen = ;
  24. int leftlen = ;
  25. char *ptr = NULL;
  26. memset((void *)&hostaddr, , sizeof(hostaddr));
  27. memset((void *)&clientaddr, , sizeof(clientaddr));
  28. hostaddr.sin_family = AF_INET;
  29. hostaddr.sin_port = htons(LISTEN_PORT);
  30. hostaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  31. listen_sock = socket(AF_INET, SOCK_STREAM, );
  32. if(listen_sock < )
  33. {
  34. syslog(LOG_ERR, "%s:%d, create socket failed", __FILE__, __LINE__);
  35. exit();
  36. }
  37. if(bind(listen_sock, (struct sockaddr *)&hostaddr, sizeof(hostaddr)) < )
  38. {
  39. syslog(LOG_ERR, "%s:%d, bind socket failed", __FILE__, __LINE__);
  40. exit();
  41. }
  42. if(listen(listen_sock, MAX_LISTEN_NUM) < )
  43. {
  44. syslog(LOG_ERR, "%s:%d, listen failed", __FILE__, __LINE__);
  45. exit();
  46. }
  47. while()
  48. {
  49. app_sock = accept(listen_sock, (struct sockaddr *)&clientaddr, &socklen);
  50. if(app_sock < )
  51. {
  52. syslog(LOG_ERR, "%s:%d, accept failed", __FILE__, __LINE__);
  53. exit();
  54. }
  55. sprintf(sendbuf, "welcome %s:%d here!/n", inet_ntoa(clientaddr.sin_addr.s_addr), clientaddr.sin_port);
  56. //send data
  57. sendlen = strlen(sendbuf) +;
  58. retlen = ;
  59. leftlen = sendlen;
  60. ptr = sendbuf;
  61. //while(leftlen)
  62. {
  63. retlen = send(app_sock, ptr, sendlen, );
  64. if(retlen < )
  65. {
  66. if(errno == EINTR)
  67. retlen = ;
  68. else
  69. exit();
  70. }
  71. leftlen -= retlen;
  72. ptr += retlen;
  73. }
  74. //receive data
  75. recvlen = ;
  76. retlen = ;
  77. ptr = recvbuf;
  78. leftlen = RECV_BUF_SIZE -;
  79. //do
  80. {
  81. retlen = recv(app_sock, ptr, leftlen, ) ;
  82. if(retlen < )
  83. {
  84. if(errno == EINTR)
  85. retlen = ;
  86. else
  87. exit();
  88. }
  89. recvlen += retlen;
  90. leftlen -= retlen;
  91. ptr += retlen;
  92. }
  93. //while(recvlen && leftlen);
  94. printf("receive data is : %s", recvbuf);
  95. close(app_sock);
  96. }
  97. close(listen_sock);
  98.  
  99. return ;
  100.  
  101. }

客户端代码为:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <syslog.h>
  6. #include <errno.h>
  7. #include <stdlib.h>
  8. #define MAX_LISTEN_NUM 5
  9. #define SEND_BUF_SIZE 100
  10. #define RECV_BUF_SIZE 100
  11. #define SERVER_PORT 1010
  12. int main()
  13. {
  14. int sock_fd = ;
  15. char recvbuf[RECV_BUF_SIZE] = {};
  16. char sendbuf[SEND_BUF_SIZE] = {};
  17. int recvlen = ;
  18. int retlen = ;
  19. int sendlen = ;
  20. int leftlen = ;
  21. char *ptr = NULL;
  22. struct sockaddr_in ser_addr;
  23.  
  24. memset(&ser_addr, , sizeof(ser_addr));
  25. ser_addr.sin_family = AF_INET;
  26. inet_aton("127.0.0.1", (struct in_addr *)&ser_addr.sin_addr);
  27. ser_addr.sin_port = htons(SERVER_PORT);
  28. sock_fd = socket(AF_INET, SOCK_STREAM, );
  29. if(sock_fd < )
  30. {
  31. syslog(LOG_ERR, "%s:%d, create socket failed", __FILE__, __LINE__);
  32. exit();
  33. }
  34. if(connect(sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) < )
  35. {
  36. syslog(LOG_ERR, "%s:%d, connect socket failed", __FILE__, __LINE__);
  37. exit();
  38. }
  39. //receive data
  40. recvlen = ;
  41. retlen = ;
  42. ptr = recvbuf;
  43. leftlen = RECV_BUF_SIZE -;
  44. //do
  45. {
  46. retlen = recv(sock_fd, ptr, leftlen, ) ;
  47. if(retlen < )
  48. {
  49. if(errno == EINTR)
  50. retlen = ;
  51. else
  52. exit();
  53. }
  54. recvlen += retlen;
  55. leftlen -= retlen;
  56. ptr += retlen;
  57. }
  58. //while(recvlen && leftlen);
  59. printf("receive data is : %s", recvbuf);
  60. sprintf(sendbuf, "hello server/n");
  61. //send data
  62. sendlen = strlen(sendbuf) +;
  63. retlen = ;
  64. leftlen = sendlen;
  65. ptr = sendbuf;
  66. // while(leftlen)
  67. {
  68. retlen = send(sock_fd, ptr, sendlen, );
  69. if(retlen < )
  70. {
  71. if(errno == EINTR)
  72. retlen = ;
  73. else
  74. exit();
  75. }
  76. leftlen -= retlen;
  77. ptr += retlen;
  78. }
  79. close(sock_fd);
  80.  
  81. }

现在一个简单的使用tcp的socket通信的例子已经完成了,这里有几个需要说明的问题

1)头文件:

sys/socket.h   包含了socket相关的函数,如socket,send 和recv, 以及struct sockaddr等

netinet/in.h    包含了地址结构,如struct sockaddr_in

errno.h           包含了errno 和 EINTR

syslog.h         包含了syslog相关的信息,其打印结果在/var/log/messages里面

2)socket地址

对于IPv4来说,其地址用的是struct sockaddr_in,具体结构如下

  1. struct in_addr {
  2. in_addr_t s_addr; /* 32-bit IPv4 address */
  3. /* network byte ordered */
  4. };
  5.  
  6. struct sockaddr_in {
  7. uint8_t sin_len; /* length of structure (16) */
  8. sa_family_t sin_family; /* AF_INET */
  9. in_port_t sin_port; /* 16-bit TCP or UDP port number */
  10. /* network byte ordered */
  11. struct in_addr sin_addr; /* 32-bit IPv4 address */
  12. /* network byte ordered */
  13. char sin_zero[]; /* unused */
  14. };
  1. 其中sin_len我们一般不关注,也不填(只有在使用routing socket的时候才用到,被内核用来处理各种协议簇的地址结构)。
  2. bind, connect, sendto, sendmsg会把socket地址从程序传递给内核; accept, recvfrom, recvmsg, getpeername,
    getsockname会把地址从内核传递给程序。因为不同协议簇的地址结构是不一样的,所以必须要有一个通用的指针来传递地址,
    对于ANSI C来说我们一般使用void *,但是socket产生早于ANSI C,所以也就没有使用这个机制,而是使用一个通用的地址结构
    struct sockaddr来处理的
  1. struct sockaddr {
  2. uint8_t sa_len;
  3. sa_family_t sa_family; /* address family: AF_xxx value */
  4. char sa_data[]; /* protocol-specific address */
  5. };
  1. IPv6socket地址为struct sockaddr_in6
  1.  
  1. struct in6_addr {
  2. uint8_t s6_addr[]; /* 128-bit IPv6 address */
  3. /* network byte ordered */
  4. };
  5.  
  6. #define SIN6_LEN /* required for compile-time tests */
  7.  
  8. struct sockaddr_in6 {
  9. uint8_t sin6_len; /* length of this struct (28) */
  10. sa_family_t sin6_family; /* AF_INET6 */
  11. in_port_t sin6_port; /* transport layer port# */
  12. /* network byte ordered */
  13. uint32_t sin6_flowinfo; /* flow information, undefined */
  14. struct in6_addr sin6_addr; /* IPv6 address */
  15. /* network byte ordered */
  16. uint32_t sin6_scope_id; /* set of interfaces for a scope */
  17. };
  1.  
  1. 对于sockaddr-in6来说,我们不能用通用的地址struct sockaddr来存储了,而是产用新的通用地址结构struct sockaddr_storage
    这个结构足够大可以存储任何系统支持的地址。
  1. struct sockaddr_storage {
  2. uint8_t ss_len; /* length of this struct (implementation dependent) */
  3. sa_family_t ss_family; /* address family: AF_xxx value */
  4. /* implementation-dependent elements to provide:
  5. * a) alignment sufficient to fulfill the alignment requirements of
  6. * all socket address types that the system support
  7. * b) enough storage to hold any type of socket address that the
  8. * system supports.
  9. */
  10. };
  1. 几种常见的地址结构
  1. 3 相关函数的的length
  2.  
  3. 对于从程序传地址给内核的函数(如connect),其长度是一个整型值,告诉内核要copy的地址长度。
  4.  
  5. 对于从内核传递给程序的函数(如accpt),其长度是一个整型指针,是一个value-result参数。有两个目的:一告诉内核地址结构的长度,
    让内核在copy的时候不要超过这个长度;二返回内核真正copy的长度。
  6. 4)字节序
  7. socket相关的函数都是使用网络字节序
  8. 5)地址转换函数
  9. inet_aton, inet_ntoa, and inet_addrIPv4字符串地址转为32位的网络字节序地址
  10. inet_ptonand inet_ntop可以转换IPv4IPv6的地址
  11. 6listen中的backlog
  12. 要知道这个值的含义先用说一下,对于一个listensocket,有两个队列:一个是incomplete connection队列(仅仅收到SYN);
    一个是complete connection队列(三次握手完成)。accept函数就是在complete connection队列中取一个socketbacklog就是指队列的个数,
    但不行的是各个地方都没有明确定义这个值,没有说明究竟代表了哪个队列,或是两个队列之和。一般来说可以
  13. 同时处理的连接数是backlog1.5倍,很多地方都用5.
  14. 7 getsockname getpeername
  15. 这两个函数可以与socket关联的地址,getsockname getpeername分别得到自己和对端的地址
  1. int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen)
  2.  
  3. int getpeername(int sockfd , struct sockaddr * peeraddr , socklen_t * addrlen );

FROM: http://blog.csdn.net/wind19/article/details/6156339

socket编程——一个简单的例子的更多相关文章

  1. socket编程——一个简单的样例

    从一个简单的使用TCP样例開始socket编程,其基本过程例如以下: server                                                  client ++ ...

  2. socket计划——一个简单的例子

    从一个简单易用TCP样品开始socket计划,的基本过程例如下列: server                                                  client +++ ...

  3. socket编程---一个简单例子

    服务器端代码(单线程): import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamRe ...

  4. ? 原创: 铲子哥 搜狗测试 今天 shell编程的时候,往往不会把所有功能都写在一个脚本中,这样不太好维护,需要多个脚本文件协同工作。那么问题来了,在一个脚本中怎么调用其他的脚本呢?有三种方式,分别是fork、source和exec。 1. fork 即通过sh 脚本名进行执行脚本的方式。下面通过一个简单的例子来讲解下它的特性。 创建father.sh,内容如下: #!/bin/bas

    ? 原创: 铲子哥 搜狗测试 今天 shell编程的时候,往往不会把所有功能都写在一个脚本中,这样不太好维护,需要多个脚本文件协同工作.那么问题来了,在一个脚本中怎么调用其他的脚本呢?有三种方式,分别 ...

  5. socket编程,简单多线程服务端测试程序

    socket编程,简单多线程服务端测试程序 前些天重温了MSDN关于socket编程的WSAStartup.WSACleanup.socket.closesocket.bind.listen.acce ...

  6. Linux内核中的信号机制--一个简单的例子【转】

    本文转载自:http://blog.csdn.net/ce123_zhouwei/article/details/8562958 Linux内核中的信号机制--一个简单的例子 Author:ce123 ...

  7. 用一个简单的例子来理解python高阶函数

    ============================ 用一个简单的例子来理解python高阶函数 ============================ 最近在用mailx发送邮件, 写法大致如 ...

  8. Spring-Context之一:一个简单的例子

    很久之前就想系统的学习和掌握Spring框架,但是拖了很久都没有行动.现在趁着在外出差杂事不多,就花时间来由浅入深的研究下Spring框架.Spring框架这几年来已经发展成为一个巨无霸产品.从最初的 ...

  9. 关于apriori算法的一个简单的例子

    apriori算法是关联规则挖掘中很基础也很经典的一个算法,我认为很多教程出现大堆的公式不是很适合一个初学者理解.因此,本文列举一个简单的例子来演示下apriori算法的整个步骤. 下面这个表格是代表 ...

随机推荐

  1. JAVA 代码开发规范

    一.开发工具规范: 1. 开发工具经项目负责人调试后统一确定. 2. 开发工具一经确定不允许集成任何非统一插件,若有需要,经项目负责人同意后统一为 项目组成员添加. 3. 开发工具的编码格式不允许修改 ...

  2. 标签<a>的注意事项1

    使用a标签时,其子元素可以为其他元素,但是不能包含<a>标签,否则会造成布局改变! 因此请尽量不要在a标签里放太多子元素,可以在外层套一个div,其他子元素放在a标签同级下. 正确布局: ...

  3. 第一百二十七节,JavaScript,JSON数据类型转换,数据转换成字符串,字符串转换成数据

    第一百二十七节,JavaScript,JSON数据类型转换,数据转换成字符串,字符串转换成数据 学习要点: 1.JSON语法 2.解析和序列化 前两章我们探讨了XML的结构化数据,但开发人员还是觉得这 ...

  4. STM32 Keil查看程序占用ROM和RAM

    1. 编译生成的map文件中code , RO ,RW, ZI 表示内容 Code为程序代码部分 RO-data 表示 程序定义的常量const temp; RW-data 表示 已初始化的全局变量 ...

  5. JSTL标签库--核心标签库

    ->JSTL的使用和EL表达式是分不开的 ->JSTL标签库分为5类 1.核心标签库(这里只介绍该标签库) 2.I18N格式化标签库 3.SQL标签库 4.XML标签库 5.函数标签库 - ...

  6. Java 不使用科学计数法表示数据设置

    java.text.NumberFormat nf = java.text.NumberFormat.getInstance(); nf.setGroupingUsed(false); nf.form ...

  7. Android中AlertDialog对话框禁止按[返回键]或[搜索键]

    alertDialog.setOnKeyListener(new DialogInterface.OnKeyListener() { @Override public boolean onKey(Di ...

  8. 常用的html标签大全

    html标签大全 一.文字 1.标题文字 <h#>..........</h#> #=1~6:h1为最大字,h6为最小字 2.字体变化 <font>........ ...

  9. [Q]自定义纸张大小

    问:当打印机纸张列表里没有符合要求的纸张大小,例如如何打印加长图?答:当打印非标准图框时,你可能在图纸列表里找不到想要纸幅.你需要自己新建你需要的纸幅,以pdfFactory虚拟打印机为例(其它打印机 ...

  10. Fedora25

    Fedora默认情况是没有装flash的,首先输入https://get.adobe.com/flashplayer/?loc=cn,选择.rpm包,点击立即下载,下载完成后进到download目录, ...