基于C语言的Linux环境下socket编程

https://www.write-bug.com/article/1274.html

一 需求分析

柏克莱套接字,又称为BSD 套接字是一种应用程序接口,用于网际插座与Unix域套接字,包括了一个用C语言写成的应用程序开发库,主要用于实现进程间通讯,在计算机网络通讯方面被广泛使用。

使用Berkeley套接字的系统有很多,本系统是在Ubuntu下用C语言进行socket编程。

二 程序设计

2.1 系统流程设计

如下图所示:

2.2 数据结构设计

socket编程问题中涉及的数据结构包括 套接口地址结等。

为了实现这些数据结构,用C语言定义变量如下:

  
  
  1. structsockaddr_in {
  2. sa_family_t sin_family;
  3. in_port_t sin_port;
  4. struct in_addr sin_addr;
  5. };

三 程序实现

3.1 TCP通信流程

如下图所示:

3.2 实现技术

为实现上述设计,采用C语言,gcc4.9.2 + Vim开发环境。具体采用的技术如下:

  • socket()函数 int socket(int domain, int type, int protocol);

  • bind()函数 intbind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

  • listen()函数 int listen(int sockfd, int backlog);

  • connect()函数 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

  • accept()函数 int accept(int sockfd, struct sockaddr addr, socklen_t addrlen);

  • close()函数 int close(int fd);

实现步骤如下

  • gcc -o server server.c

  • gcc -o client client.c

  • ./server

  • ./client

3.3 关键代码说明

为了进一步了解操作系统内核,学习了Linux操作系统的进程同步程序,主要程序源代码如下:

  
  
  1. -----------------------client.c---------------------
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <stdio.h>
  5. #include <netinet/in.h>
  6. #include <arpa/inet.h>
  7. #include <unistd.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include <fcntl.h>
  11. #include <sys/shm.h>
  12. #define MYPORT 8887
  13. #define BUFFER_SIZE 1024
  14. int main() {
  15. ///定义sockfd
  16. int sock_cli = socket(AF_INET,SOCK_STREAM, 0);
  17. ///定义sockaddr_in
  18. struct sockaddr_in servaddr;
  19. memset(&servaddr, 0, sizeof(servaddr));
  20. servaddr.sin_family = AF_INET;
  21. servaddr.sin_port = htons(MYPORT); ///服务器端口
  22. servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip
  23. ///连接服务器,成功返回0,错误返回-1
  24. if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
  25. perror("connect");
  26. exit(1);
  27. }
  28. char sendbuf[BUFFER_SIZE];
  29. char recvbuf[BUFFER_SIZE];
  30. memset(recvbuf, '\0', sizeof(recvbuf));
  31. while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) {
  32. send(sock_cli, sendbuf, strlen(sendbuf),0); ///发送
  33. if(strcmp(sendbuf,"q\n")==0)
  34. break;
  35. recv(sock_cli, recvbuf, sizeof(recvbuf),0); ///接收
  36. fputs(recvbuf, stdout);
  37. memset(sendbuf, 0, sizeof(sendbuf));
  38. memset(recvbuf, 0, sizeof(recvbuf));
  39. }
  40. close(sock_cli);
  41. return 0;
  42. }
  43. -----------------------server.c-----------------------
  44. #include <sys/types.h>
  45. #include <sys/socket.h>
  46. #include <stdio.h>
  47. #include <netinet/in.h>
  48. #include <arpa/inet.h>
  49. #include <unistd.h>
  50. #include <string.h>
  51. #include <stdlib.h>
  52. #include <fcntl.h>
  53. #include <sys/shm.h>
  54. #define MYPORT 8887
  55. #define QUEUE 20
  56. #define BUFFER_SIZE 1024
  57. char ans[BUFFER_SIZE];
  58. void _itoa(int n) {
  59. char ans2[BUFFER_SIZE];
  60. int l = 0;
  61. while (n) {
  62. ans2[l++] = n % 10 + '0';
  63. n /= 10;
  64. }
  65. int l2 = 0;
  66. while (l) {
  67. ans[l2++] = ans2[--l];
  68. }
  69. ans[l2++] = '\n';
  70. ans[l2] = '\0';
  71. }
  72. int main() {
  73. ///定义sockfd
  74. int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);
  75. ///定义sockaddr_in
  76. struct sockaddr_in server_sockaddr;
  77. server_sockaddr.sin_family = AF_INET;
  78. server_sockaddr.sin_port = htons(MYPORT);
  79. server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  80. ///bind,成功返回0,出错返回-1
  81. if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1) {
  82. perror("bind");
  83. exit(1);
  84. }
  85. ///listen,成功返回0,出错返回-1
  86. if(listen(server_sockfd,QUEUE) == -1) {
  87. perror("listen");
  88. exit(1);
  89. }
  90. ///客户端套接字
  91. char buffer[BUFFER_SIZE];
  92. struct sockaddr_in client_addr;
  93. socklen_t length = sizeof(client_addr);
  94. ///成功返回非负描述字,出错返回-1
  95. int conn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length);
  96. if(conn<0) {
  97. perror("connect");
  98. exit(1);
  99. }
  100. while(1) {
  101. memset(buffer,0,sizeof(buffer));
  102. int len = recv(conn, buffer, sizeof(buffer),0);
  103. if(strcmp(buffer,"q\n")==0)
  104. break;
  105. int a = 0;
  106. int i, blen = strlen(buffer);
  107. for (i = 2; i < blen - 1; i++) {
  108. if (buffer[i] != ',') {
  109. a = a * 10 + buffer[i] - '0';
  110. } else {
  111. i++;
  112. break;
  113. }
  114. }
  115. int b = 0;
  116. for (; i < blen - 1; i++) {
  117. b = b * 10 + buffer[i] - '0';
  118. }
  119. _itoa(a+b);
  120. fputs(buffer, stdout);
  121. send(conn, ans, strlen(ans), 0);
  122. }
  123. close(conn);
  124. close(server_sockfd);
  125. return 0;
  126. }

这一段程序的主要功能为:

  • 向server发送要计算的表达式并接收计算结果

  • 接收client发送的表达式并计算,在终端输出表达式并把计算结果发回到client

四 运行测试

例如,客户端输入+,100,200,根据分析,运行结果应为:300

实际运行结果如下:

上传的附件 cloud_download 基于C语言的Linux环境下socket编程.7z ( 385.76kb, 8次下载 )
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值