转自:http://blog.csdn.net/taiyang1987912/article/details/49738351

一、简介

通过socket扫描本机打开的tcp端口号,模拟用户名、密码登录服务器的过程、socket文件传输及模仿http服务器。

二、详解

1、Linux下tcp端口扫描

(1)scanport.c:

[html] view plaincopy
  1. // 端口扫描程序,只支持扫描TCP端口
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <errno.h>
  7. #include <pthread.h>
  8. #include <sys/types.h>
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>
  11. #include <arpa/inet.h>
  12. // 定义一个端口区间信息
  13. typedef struct _port_segment {
  14. struct in_addr       dest_ip;   // 目标IP
  15. unsigned short int  min_port;   // 起始端口
  16. unsigned short int  max_port;   // 最大端口
  17. } port_segment;
  18. /*自定义的错误处理函数*/
  19. void my_err(const char * err_string, int line)
  20. {
  21. fprintf(stderr, "line:%d  ", line);
  22. perror(err_string);
  23. exit(1);
  24. }
  25. /*
  26. * 描  述:扫描某一IP地址上的某一个端口的函数
  27. * 返回值:-1  出错
  28. *     0   目标端口未打开
  29. *     1   目标端口已打开
  30. */
  31. int do_scan(struct sockaddr_in serv_addr)
  32. {
  33. int     conn_fd;
  34. int     ret;
  35. // 创建一个TCP套接字
  36. conn_fd = socket(AF_INET, SOCK_STREAM,0);
  37. if (conn_fd < 0) {
  38. my_err("socket", __LINE__);
  39. }
  40. // 向服务器端发送连接请求
  41. if ((ret = connect(conn_fd, (struct sockaddr *)&serv_addr, sizeof (struct sockaddr))) < 0 ) {
  42. if (errno == ECONNREFUSED) {    // 目标端口未打开
  43. close(conn_fd);
  44. return 0;
  45. } else {    // 其他错误
  46. close(conn_fd);
  47. return -1;
  48. }
  49. } else if (ret == 0){
  50. printf("port %d found in %s\n", ntohs(serv_addr.sin_port),
  51. inet_ntoa(serv_addr.sin_addr));
  52. close(conn_fd);
  53. return 1;
  54. }
  55. return -1;  // 实际执行不到这里,只是为了消除编译程序时产生的警告
  56. }
  57. // 执行扫描的线程,扫描某一区间的端口
  58. void * scaner(void *arg)
  59. {
  60. unsigned short int  i;
  61. struct sockaddr_in  serv_addr;
  62. port_segment        portinfo;     // 端口信息
  63. // 读取端口区间信息
  64. memcpy(&portinfo, arg, sizeof(struct _port_segment));
  65. // 初始化服务器端地址结构
  66. memset(&serv_addr, 0, sizeof (struct sockaddr_in));
  67. serv_addr.sin_family = AF_INET;
  68. serv_addr.sin_addr.s_addr = portinfo.dest_ip.s_addr;
  69. //printf("******serv_addr.sin_addr.s_addr=%s\n", serv_addr.sin_addr.s_addr);
  70. //printf("*******portinfo.min_port=%d, portinfo.max_port=%d\n", portinfo.min_port, portinfo.max_port);
  71. for (i=portinfo.min_port; i<=portinfo.max_port; i++) {
  72. serv_addr.sin_port = htons(i);
  73. if (do_scan(serv_addr) < 0) {
  74. continue;   // 出错则退出进程
  75. }
  76. }
  77. return NULL;
  78. }
  79. /*
  80. * 命令行参数:-m 最大端口, -a 目标主机的IP地址,  -n 最大线程数
  81. */
  82. int main(int argc, char **argv)
  83. {
  84. pthread_t*  thread;         // 指向所有的线程ID
  85. int     max_port;       // 最大端口号
  86. int     thread_num;     // 最大线程数
  87. int     seg_len;        // 端口区间长度
  88. struct in_addr dest_ip;         // 目标主机IP
  89. int     i;
  90. // 检查参数个数
  91. if (argc != 7) {
  92. printf("Usage: [-m] [max_port] [-a] [serv_address] [-n] [thread_number]\n");
  93. exit(1);
  94. }
  95. // 解析命令行参数
  96. for (i=1; i<argc; i++) {
  97. if (strcmp("-m", argv[i]) == 0) {
  98. max_port = atoi(argv[i+1]);   // 将字符串转化为对应的整数
  99. if (max_port < 0 || max_port >= 65535) {   //65535会导致死循环
  100. printf("Usage:invalid max dest port\n");
  101. exit(1);
  102. }
  103. continue;
  104. }
  105. if (strcmp("-a", argv[i]) == 0) {
  106. if (inet_aton(argv[i+1], &dest_ip) == 0) {
  107. printf("Usage:invalid dest ip address\n");
  108. exit(1);
  109. }
  110. continue;
  111. }
  112. if (strcmp("-n", argv[i]) == 0) {
  113. thread_num = atoi(argv[i+1]);
  114. if (thread_num <= 0) {
  115. printf("Usage:invalid thread_number\n");
  116. exit(1);
  117. }
  118. continue;
  119. }
  120. }
  121. // 如果输入的最大端口号小于线程数,则将线程数设为最大端口号
  122. if (max_port < thread_num) {
  123. thread_num = max_port;
  124. }
  125. seg_len = max_port / thread_num;
  126. if ( (max_port%thread_num) != 0 ) {
  127. thread_num += 1;
  128. }
  129. //printf("max_port=%d, seg_len=%d, thread_num = %d\n", max_port, seg_len, thread_num);
  130. // 分配存储所有线程ID的内存空间
  131. thread = (pthread_t*)malloc(thread_num*sizeof(pthread_t));
  132. // 创建线程,根据最大端口号和线程数分配每个线程扫描的端口区间
  133. port_segment *portinfo = (port_segment*)malloc(thread_num * sizeof(port_segment));
  134. for (i=0; i<thread_num; i++) {
  135. portinfo[i].dest_ip = dest_ip;
  136. portinfo[i].min_port = i*seg_len + 1;
  137. //printf("portinfo.min_port=%d, seg_len=%d, i = %d\n", portinfo[i].min_port, seg_len, i);
  138. if (i == thread_num - 1) {
  139. portinfo[i].max_port = max_port;
  140. } else {
  141. portinfo[i].max_port = portinfo[i].min_port + seg_len - 1;
  142. }
  143. // 创建线程
  144. //if (pthread_create(&thread[i], NULL, scaner, (void *)(portinfo + i)) != 0) {
  145. if (pthread_create(&thread[i], NULL, scaner, (void *)(&portinfo[i])) != 0) {
  146. my_err("pthread_create", __LINE__);
  147. }
  148. }
  149. for (i=0; i<thread_num; i++) {
  150. // 主线程等待子线程结束
  151. pthread_join(thread[i], NULL);
  152. }
  153. free(portinfo);
  154. return 0;
  155. }

(2)编译运行

[html] view plaincopy
  1. gcc -o scanport scanport.c  -lpthread
  2. ./scanport -m 65534 -a 127.0.0.1 -n 1


       可以通过netstat查看网络相关信息,netstat -tnlp或netstat -tnlpc比较打开的tcp端口号。

2、模拟用户名、密码登录

(1)服务器server.c:

[html] view plaincopy
  1. // Client/Server模型的服务器端
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <unistd.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include <errno.h>
  10. #include <stdlib.h>
  11. #define BUFSIZE 1024
  12. #define SERV_PORT       4507    // 服务器端的端口
  13. #define LISTENQ         12  // 连接请求队列的最大长度
  14. #define INVALID_USERINFO    'n' // 用户信息无效
  15. #define VALID_USERINFO      'y' // 用户信息有效
  16. #define USERNAME        0   // 接收到的是用户名
  17. #define PASSWORD        1   // 接收到的是密码
  18. struct userinfo {   // 保存用户名和密码的结构体
  19. char username[32];
  20. char password[32];
  21. };
  22. struct userinfo users[ ] = {
  23. {"linux", "unix"},
  24. {"4507", "4508"},
  25. {"clh", "clh"},
  26. {"xl", "xl"},
  27. {" "," "}       // 以只含一个空格的字符串作为数组的结束标志
  28. };
  29. /*自定义的错误处理函数*/
  30. void my_err(const char * err_string, int line)
  31. {
  32. fprintf(stderr, "line:%d  ", line);
  33. perror(err_string);
  34. exit(1);
  35. }
  36. /*
  37. * 函数名: my_recv
  38. * 描 述 : 从套接字上读取一次数据(以'\n'为结束标志)
  39. * 参 数 : conn_fd     -- 从该连接套接字上接收数据
  40. *     data_buf  -- 读取到的数据保存在此缓冲中
  41. *     len       -- data_buf所指向的空间长度
  42. * 返回值: 出错返回-1, 服务器端已关闭连接则返回0, 成功返回读取的字节数
  43. */
  44. int my_recv(int conn_fd, char *data_buf, int len)
  45. {
  46. static  char    recv_buf[BUFSIZE];  // 自定义缓冲区,BUFSIZE定义在my_recv.h中
  47. static  char    *pread;         // 指向下一次读取数据的位置
  48. static  int len_remain = 0;     // 自定义缓冲区中剩余字节数
  49. int         i;
  50. // 如果自定义缓冲区中没有数据,则从套接字读取数据
  51. if (len_remain <= 0) {
  52. if ((len_remain =recv(conn_fd, recv_buf, sizeof (recv_buf), 0)) < 0) {
  53. my_err("recv", __LINE__);
  54. } else if (len_remain == 0) {   // 目的计算机端的socket连接关闭
  55. return 0;
  56. }
  57. pread = recv_buf;   // 重新初始化pread指针
  58. }
  59. // 从自定义缓冲区中读取一次数据
  60. for (i=0; *pread != '\n'; i++) {
  61. if (i > len) {   // 防止指针越界
  62. return -1;
  63. }
  64. data_buf[i] = *pread++;
  65. len_remain--;
  66. }
  67. // 去除结束标志
  68. len_remain--;
  69. pread++;
  70. return i;   // 读取成功
  71. }
  72. // 查找用户名是否存在,存在返回该用户名的下标,不存在则返回-1,出错返回-2
  73. int find_name(const char *name)
  74. {
  75. int i;
  76. if (name == NULL) {
  77. printf("in find_name, NULL pointer");
  78. return -2;
  79. }
  80. for (i=0; users[i].username[0] != ' ';i++) {
  81. if (strncmp(users[i].username, name, strlen(users[i].username)) == 0) {
  82. return i;
  83. }
  84. }
  85. return -1;
  86. }
  87. // 发送数据
  88. void send_data(int conn_fd, const char *string)
  89. {
  90. if (send(conn_fd, string, strlen(string), 0) < 0) {
  91. my_err("send", __LINE__);  // my_err函数在my_recv.h中声明
  92. }
  93. }
  94. int main()
  95. {
  96. int         sock_fd, conn_fd;
  97. int         optval;
  98. int         flag_recv = USERNAME; // 标识接收到的是用户还是密码
  99. int         ret;
  100. int         name_num;
  101. pid_t           pid;
  102. socklen_t       cli_len;
  103. struct sockaddr_in  cli_addr, serv_addr;
  104. char            recv_buf[128];
  105. // 创建一个TCP套接字
  106. sock_fd = socket(AF_INET, SOCK_STREAM,0);
  107. if (sock_fd < 0) {
  108. my_err("socket", __LINE__);
  109. }
  110. // 设置该套接字使之可以重新绑定端口
  111. optval = 1;
  112. if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
  113. (void *)&optval, sizeof(int)) < 0) {
  114. my_err("setsockopt", __LINE__);
  115. }
  116. // 初始化服务器端地址结构
  117. memset(&serv_addr, 0, sizeof (struct sockaddr_in));
  118. serv_addr.sin_family = AF_INET;
  119. serv_addr.sin_port = htons(SERV_PORT);
  120. serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  121. // 将套接字绑定到本地端口
  122. if (bind(sock_fd, (struct sockaddr *)&serv_addr,
  123. sizeof (struct sockaddr_in)) < 0) {
  124. my_err("bind", __LINE__);
  125. }
  126. // 将套接字转化为监听套接字
  127. if (listen(sock_fd, LISTENQ) < 0) {
  128. my_err("listen", __LINE__);
  129. }
  130. cli_len = sizeof (struct sockaddr_in);
  131. while (1) {
  132. // 通过accept接受客户端的连接请求,并返回连接套接字用于收发数据
  133. conn_fd = accept(sock_fd, (struct sockaddr *)&cli_addr, &cli_len);
  134. if (conn_fd < 0) {
  135. my_err("accept", __LINE__);
  136. }
  137. printf("accept a new client, ip:%s\n", inet_ntoa(cli_addr.sin_addr));
  138. // 创建一个子进程处理刚刚接受的连接请求
  139. if ( (pid = fork()) == 0 ) {    // 子进程
  140. while(1) {
  141. memset(recv_buf, 0, sizeof(recv_buf));
  142. if ((ret = recv(conn_fd, recv_buf, sizeof (recv_buf), 0)) < 0) {
  143. perror("recv");
  144. exit(1);
  145. }
  146. recv_buf[ret-1] = '\0'; // 将数据结束标志'\n'替换成字符串结束标志
  147. if (flag_recv == USERNAME) {    // 接收到的是用户名
  148. name_num = find_name(recv_buf);
  149. switch (name_num) {
  150. case -1:
  151. send_data(conn_fd, "n\n");
  152. break;
  153. case -2:
  154. exit(1);
  155. break;
  156. default:
  157. send_data(conn_fd, "y\n");
  158. flag_recv = PASSWORD;
  159. break;
  160. }
  161. } else if (flag_recv == PASSWORD) {  // 接收到的是密码
  162. if (strncmp(users[name_num].password, recv_buf, strlen(users[name_num].password)) == 0) {
  163. send_data(conn_fd, "y\n");
  164. send_data(conn_fd, "Welcome login my tcp server\n");
  165. printf("%s login\n", users[name_num].username);
  166. break; // 跳出while循环
  167. } else
  168. send_data(conn_fd, "n\n");
  169. }
  170. }
  171. close(sock_fd);
  172. close(conn_fd);
  173. exit(0);  // 结束子进程
  174. } else {   // 父进程关闭刚刚接受的连接请求,执行accept等待其他连接请求
  175. close(conn_fd);
  176. }
  177. }
  178. return 0;
  179. }

(2)客户端client.c:

[html] view plaincopy
  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <unistd.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <stdlib.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #define BUFSIZE 1024
  11. #define INVALID_USERINFO    'n' // 用户信息无效
  12. #define VALID_USERINFO      'y' // 用户信息有效
  13. /*自定义的错误处理函数*/
  14. void my_err(const char * err_string, int line)
  15. {
  16. fprintf(stderr, "line:%d  ", line);
  17. perror(err_string);
  18. exit(1);
  19. }
  20. /*
  21. * 函数名: my_recv
  22. * 描 述 : 从套接字上读取一次数据(以'\n'为结束标志)
  23. * 参 数 : conn_fd     -- 从该连接套接字上接收数据
  24. *     data_buf  -- 读取到的数据保存在此缓冲中
  25. *     len       -- data_buf所指向的空间长度
  26. * 返回值: 出错返回-1, 服务器端已关闭连接则返回0, 成功返回读取的字节数
  27. */
  28. int my_recv(int conn_fd, char *data_buf, int len)
  29. {
  30. static  char    recv_buf[BUFSIZE];  // 自定义缓冲区,BUFSIZE定义在my_recv.h中
  31. static  char    *pread;         // 指向下一次读取数据的位置
  32. static  int len_remain = 0;     // 自定义缓冲区中剩余字节数
  33. int         i;
  34. // 如果自定义缓冲区中没有数据,则从套接字读取数据
  35. if (len_remain <= 0) {
  36. if ((len_remain =recv(conn_fd, recv_buf, sizeof (recv_buf), 0)) < 0) {
  37. my_err("recv", __LINE__);
  38. } else if (len_remain == 0) {   // 目的计算机端的socket连接关闭
  39. return 0;
  40. }
  41. pread = recv_buf;   // 重新初始化pread指针
  42. }
  43. // 从自定义缓冲区中读取一次数据
  44. for (i=0; *pread != '\n'; i++) {
  45. if (i > len) {   // 防止指针越界
  46. return -1;
  47. }
  48. data_buf[i] = *pread++;
  49. len_remain--;
  50. }
  51. // 去除结束标志
  52. len_remain--;
  53. pread++;
  54. return i;   // 读取成功
  55. }
  56. /*获取用户输入存入到buf,buf的长度为len,用户输入数据以'\n'为结束标志*/
  57. int get_userinfo(char *buf, int len)
  58. {
  59. int i;
  60. int c;
  61. if (buf == NULL) {
  62. return -1;
  63. }
  64. i = 0;
  65. while ( ((c = getchar()) != '\n') && (c != EOF) && (i < len-2) ) {
  66. buf[i++] = c;
  67. }
  68. buf[i++] = '\n';
  69. buf[i++] = '\0';
  70. return 0;
  71. }
  72. // 输入用户名,然后通过fd发送出去
  73. void input_userinfo(int conn_fd, const char *string)
  74. {
  75. char    input_buf[32];
  76. char    recv_buf[BUFSIZE];
  77. int flag_userinfo;
  78. int count = 0;
  79. // 输入用户信息直到正确为止
  80. do {
  81. printf("%s:", string);
  82. if (get_userinfo(input_buf, 32) < 0) {
  83. printf("error return from get_userinfo\n");
  84. exit(1);
  85. }
  86. if (send(conn_fd, input_buf, strlen(input_buf), 0) < 0) {
  87. my_err("send", __LINE__);
  88. }
  89. // 从连接套接字上读取一次数据
  90. if (my_recv(conn_fd, recv_buf, sizeof (recv_buf)) < 0) {
  91. printf("data is too long\n");
  92. exit(1);
  93. }
  94. if (recv_buf[0] == VALID_USERINFO) {
  95. flag_userinfo = VALID_USERINFO;
  96. } else {
  97. count++;
  98. if (count >= 3) {
  99. printf("input %s error for three times,exit!\n", string);
  100. exit(-1);
  101. }
  102. printf("%s error,input again!\n", string);
  103. flag_userinfo= INVALID_USERINFO;
  104. }
  105. } while(flag_userinfo == INVALID_USERINFO);
  106. }
  107. int main(int argc, char **argv)
  108. {
  109. int         i;
  110. int         ret;
  111. int         conn_fd;
  112. int         serv_port;
  113. struct sockaddr_in  serv_addr;
  114. char            recv_buf[BUFSIZE];
  115. // 检查参数个数
  116. if (argc != 5) {
  117. printf("Usage: [-p] [serv_port] [-a] [serv_address]\n");
  118. exit(1);
  119. }
  120. // 初始化服务器端地址结构
  121. memset(&serv_addr, 0, sizeof (struct sockaddr_in));
  122. serv_addr.sin_family = AF_INET;
  123. // 从命令行获取服务器端的端口与地址
  124. for (i=1; i<argc; i++) {
  125. if (strcmp("-p", argv[i]) == 0) {
  126. serv_port = atoi(argv[i+1]);
  127. if (serv_port < 0 || serv_port > 65535) {
  128. printf("invalid serv_addr.sin_port\n");
  129. exit(1);
  130. } else {
  131. serv_addr.sin_port = htons(serv_port);
  132. }
  133. continue;
  134. }
  135. if (strcmp("-a", argv[i]) == 0) {
  136. if (inet_aton(argv[i+1], &serv_addr.sin_addr) == 0) {
  137. printf("invalid server ip address\n");
  138. exit(1);
  139. }
  140. continue;
  141. }
  142. }
  143. // 检测是否少输入了某项参数
  144. if (serv_addr.sin_port == 0 || serv_addr.sin_addr.s_addr == 0) {
  145. printf("Usage: [-p] [serv_addr.sin_port] [-a][serv_address]\n");
  146. exit(1);
  147. }
  148. // 创建一个TCP套接字
  149. conn_fd = socket(AF_INET, SOCK_STREAM,0);
  150. if (conn_fd < 0) {
  151. my_err("socket", __LINE__);
  152. }
  153. // 向服务器端发送连接请求
  154. if (connect(conn_fd, (struct sockaddr *)&serv_addr, sizeof (struct sockaddr)) < 0) {
  155. my_err("connect", __LINE__);
  156. }
  157. // 输入用户名和密码
  158. input_userinfo(conn_fd, "username");
  159. input_userinfo(conn_fd, "password");
  160. // 读取欢迎信息并打印出来
  161. if ((ret = my_recv(conn_fd, recv_buf, sizeof (recv_buf))) < 0) {
  162. printf("data is too long\n");
  163. exit(1);
  164. }
  165. for (i=0; i<ret; i++) {
  166. printf("%c", recv_buf[i]);
  167. }
  168. printf("\n");
  169. close(conn_fd);
  170. return 0;
  171. }

(3)编译运行:

[html] view plaincopy
  1. gcc -o server server.c
  2. ./server
  3. gcc -o client client.c
  4. ./client -p 4507 -a 127.0.0.1

3、socket文件传输(从server端下载文件)

(1)file_server.c:

[html] view plaincopy
  1. #include <netinet/in.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <strings.h>
  8. #define HELLO_WORLD_SERVER_PORT 6666
  9. #define LENGTH_OF_LISTENQ_QUEUE 20
  10. #define BUFFER_SIZE 1024
  11. #define FILE_NAME_MAX_SIZE 512
  12. int main(int argc, char *argv[])
  13. {
  14. struct sockaddr_in server_addr;
  15. bzero(&server_addr, sizeof(server_addr));
  16. server_addr.sin_family = AF_INET;
  17. server_addr.sin_addr.s_addr = htons(INADDR_ANY);
  18. server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);
  19. int server_socket = socket(AF_INET, SOCK_STREAM, 0);
  20. if (server_socket < 0) {
  21. printf("create socket failed!\n");
  22. exit(1);
  23. }
  24. if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr))) {
  25. printf("bind socket failed!\n");
  26. exit(1);
  27. }
  28. if (listen(server_socket, LENGTH_OF_LISTENQ_QUEUE)) {
  29. printf("listen socket failed!\n");
  30. exit(1);
  31. }
  32. while (1) {
  33. struct sockaddr_in client_addr;
  34. socklen_t length = sizeof(client_addr);
  35. int new_server_scoket = accept(server_socket, (struct sockaddr*)&client_addr, &length);
  36. if (new_server_scoket < 0) {
  37. printf("accept socket failed!\n");
  38. break;
  39. }
  40. char buffer[BUFFER_SIZE];
  41. bzero(buffer, BUFFER_SIZE);
  42. length = recv(new_server_scoket, buffer, BUFFER_SIZE, 0);
  43. if (length < 0) {
  44. printf("recv data failed!\n");
  45. break;
  46. }
  47. char file_name[FILE_NAME_MAX_SIZE + 1];
  48. bzero(file_name, FILE_NAME_MAX_SIZE + 1);
  49. strncpy(file_name, buffer, strlen(file_name) > FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer));
  50. FILE *fp = fopen(file_name, "r");
  51. if (fp == NULL) {
  52. printf("File: %s not found\n", file_name);
  53. }
  54. else {
  55. bzero(buffer, BUFFER_SIZE);
  56. int file_length = 0;
  57. while((file_length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0) {
  58. printf("file_length = %d\n", file_length);
  59. if (send(new_server_scoket, buffer, file_length, 0) < 0) {
  60. printf("send file: %s failed\n", file_name);
  61. break;
  62. }
  63. bzero(buffer, BUFFER_SIZE);
  64. }
  65. fclose(fp);
  66. printf("file: %s trandfer finished\n", file_name);
  67. }
  68. close(new_server_scoket);
  69. }
  70. close(server_socket);
  71. return 0;
  72. }

(2)file_client.c:

[html] view plaincopy
  1. #include <netinet/in.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <strings.h>
  8. #define HELLO_WORLD_SERVER_PORT 6666
  9. #define BUFFER_SIZE 1024
  10. #define FILE_NAME_MAX_SIZE 512
  11. int main(int argc, char *argv[])
  12. {
  13. if (argc != 2) {
  14. printf("use:[./run][server_ipaddress]\n");
  15. exit(1);
  16. }
  17. struct sockaddr_in client_addr;
  18. bzero(&client_addr,sizeof(client_addr));
  19. client_addr.sin_family = AF_INET;
  20. if (inet_aton(argv[1], &client_addr.sin_addr) == 0) {
  21. printf("server ip address error!\n");
  22. exit(1);
  23. }
  24. client_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);
  25. socklen_t client_addr_length = sizeof(client_addr);
  26. int client_socket = socket(AF_INET, SOCK_STREAM, 0);
  27. if (client_socket < 0) {
  28. printf("create socket failed\n");
  29. exit(1);
  30. }
  31. if (connect(client_socket, (struct sockaddr*)&client_addr, client_addr_length) < 0) {
  32. printf("can not connect to address\n");
  33. exit(1);
  34. }
  35. char file_name[FILE_NAME_MAX_SIZE + 1];
  36. bzero(file_name, FILE_NAME_MAX_SIZE + 1);
  37. printf("please input file name:");
  38. scanf("%s", file_name);
  39. char buffer[BUFFER_SIZE];
  40. bzero(buffer, BUFFER_SIZE);
  41. strncpy(buffer, file_name, strlen(file_name) > BUFFER_SIZE ? BUFFER_SIZE : strlen(file_name));
  42. send(client_socket, buffer, BUFFER_SIZE, 0);
  43. FILE *fp = fopen(file_name, "w");
  44. if (fp == NULL) {
  45. printf("file can not open\n");
  46. exit(1);
  47. }
  48. bzero(buffer, BUFFER_SIZE);
  49. int length = 0;
  50. while (length = recv(client_socket, buffer, BUFFER_SIZE, 0)) {
  51. if (length < 0) {
  52. printf("recv failed\n");
  53. break;
  54. }
  55. int write_length = fwrite(buffer, sizeof(char), length, fp);
  56. if (write_length < length) {
  57. printf("file write failed\n");
  58. break;
  59. }
  60. bzero(buffer, BUFFER_SIZE);
  61. }
  62. printf("recieve file: %s from server %s finished!\n", file_name, argv[1]);
  63. close(fp);
  64. close(client_socket);
  65. return 0;
  66. }

(3)编译运行

[html] view plaincopy
  1. gcc -o server file_server.c
  2. ./server
  3. gcc -o client file_client.c
  4. ./client 127.0.0.1

server显示:

client显示:

      注:server和client放在不同的目录下,需要传输的文件yang.txt与server在同一目录下。

4、模拟http服务器

(1)http服务器server.c:

[html] view plaincopy
  1. #include <stdarg.h>
  2. #include <errno.h>
  3. #include <stdio.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <time.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <dirent.h>
  11. #include <errno.h>
  12. #include <netinet/in.h>
  13. #include <sys/socket.h>
  14. #include <resolv.h>
  15. #include <arpa/inet.h>
  16. #include <stdlib.h>
  17. #include <signal.h>
  18. #include <strings.h>
  19. #define DEFAULTIP "127.0.0.1"
  20. #define DEFAULTPORT "4040"
  21. #define DEFAULTBACK "10"
  22. #define DEFAULTDIR "/tmp/http/dir"
  23. #define DEFAULTLOG "/tmp/http/log"
  24. void prterrmsg(char *msg);
  25. #define prterrmsg(msg)        { perror(msg); abort(); }
  26. void wrterrmsg(char *msg);
  27. #define wrterrmsg(msg)        { fputs(msg, logfp); fputs(strerror(errno), logfp);fflush(logfp); abort(); }
  28. void prtinfomsg(char *msg);
  29. #define prtinfomsg(msg)        { fputs(msg, stdout);  }
  30. void wrtinfomsg(char *msg);
  31. #define wrtinfomsg(msg)        {  fputs(msg, logfp); fflush(logfp);}
  32. #define MAXBUF        1024
  33. char buffer[MAXBUF + 1];
  34. char *host = 0;
  35. char *port = 0;
  36. char *back = 0;
  37. char *dirroot = 0;
  38. char *logdir = 0;
  39. unsigned char daemon_y_n = 0;
  40. FILE *logfp;
  41. #define MAXPATH        150
  42. /*----------------------------------------
  43. *--- dir_up - 查找dirpath所指目录的上一级目录
  44. *----------------------------------------
  45. */
  46. char *dir_up(char *dirpath)
  47. {
  48. static char Path[MAXPATH];
  49. int len;
  50. strcpy(Path, dirpath);
  51. len = strlen(Path);
  52. if (len > 1 && Path[len - 1] == '/')
  53. len--;
  54. while (Path[len - 1] != '/' && len > 1)
  55. len--;
  56. Path[len] = 0;
  57. return Path;
  58. }
  59. /*------------------------------------------------------
  60. *--- AllocateMemory - 分配空间并把d所指的内容复制
  61. *------------------------------------------------------
  62. */
  63. void AllocateMemory(char **s, int l, char *d)
  64. {
  65. *s = (char *)malloc(l + 1);
  66. bzero(*s, l + 1);
  67. memcpy(*s, d, l);
  68. }
  69. /*------------------------------------------------------
  70. *--- GiveResponse - 把Path所指的内容发送到client_sock去
  71. *-------------------如果Path是一个目录,则列出目录内容
  72. *-------------------如果Path是一个文件,则下载文件
  73. *------------------------------------------------------
  74. */
  75. void GiveResponse(FILE * client_sock, char *Path)
  76. {
  77. struct dirent *dirent;
  78. struct stat info;
  79. char Filename[MAXPATH];
  80. DIR *dir;
  81. int fd, len, ret;
  82. char *p, *realPath, *realFilename, *nport;
  83. /* 获得实际工作目录或文件 */
  84. len = strlen(dirroot) + strlen(Path) + 1;
  85. realPath = (char *)malloc(len + 1);
  86. bzero(realPath, len + 1);
  87. sprintf(realPath, "%s/%s", dirroot, Path);
  88. /* 获得实际工作端口 */
  89. len = strlen(port) + 1;
  90. nport = (char *)malloc(len + 1);
  91. bzero(nport, len + 1);
  92. sprintf(nport, ":%s", port);
  93. /* 获得实际工作目录或文件的信息以判断是文件还是目录 */
  94. if (stat(realPath, &info)) {
  95. fprintf(client_sock,
  96. "HTTP/1.1 200 OK\r\nServer: DAS by Centos\r\nConnection: close\r\n\r\n"
  97. "<html>"
  98. "<meta charset=\"UTF-8\"/>"
  99. "<head><title>%d - %s</title></head>"
  100. "<body><font size=+4>Linux下目录访问服务器</font><br><hr width=\"100%%\"><br><center>"
  101. "<table border cols=3 width=\"100%%\">"
  102. , errno, strerror(errno));
  103. fprintf(client_sock,
  104. "</table><font color=\"CC0000\" size=+2>请向管理员咨询为何出现如下错误提示:\n%s %s</font></body></html>",
  105. Path, strerror(errno));
  106. goto out;
  107. }
  108. /* 处理浏览文件请求,即下载文件 */
  109. if (S_ISREG(info.st_mode)) {
  110. fd = open(realPath, O_RDONLY);
  111. len = lseek(fd, 0, SEEK_END);
  112. p = (char *) malloc(len + 1);
  113. bzero(p, len + 1);
  114. lseek(fd, 0, SEEK_SET);
  115. ret = read(fd, p, len);
  116. close(fd);
  117. fprintf(client_sock,
  118. "HTTP/1.1 200 OK\r\nServer: DAS by Centos\r\nConnection: keep-alive\r\nContent-type: application/*\r\nContent-Length:%d\r\n\r\n",
  119. len);
  120. fwrite(p, len, 1, client_sock);
  121. free(p);
  122. } else if (S_ISDIR(info.st_mode)) {
  123. /* 处理浏览目录请求 */
  124. dir = opendir(realPath);
  125. fprintf(client_sock,
  126. "HTTP/1.1 200 OK\r\nServer: DAS by Centos\r\nConnection: close\r\n\r\n"
  127. "<html>"
  128. "<meta charset=\"UTF-8\"/>"
  129. "<head><title>%s</title></head>"
  130. "<body><font size=+4>Linux下目录访问服务器</font><br><hr width=\"100%%\"><br><center>"
  131. "<table border cols=3 width=\"100%%\">", Path);
  132. fprintf(client_sock,
  133. "<caption><font size=+3>目录 %s</font></caption>\n",
  134. Path);
  135. fprintf(client_sock,
  136. "<tr><td>名称</td><td>大小</td><td>修改时间</td></tr>\n");
  137. if (dir == 0) {
  138. fprintf(client_sock,
  139. "</table><font color=\"CC0000\" size=+2>%s</font></body></html>",
  140. strerror(errno));
  141. return;
  142. }
  143. /* 读取目录里的所有内容 */
  144. while ((dirent = readdir(dir)) != 0) {
  145. if (strcmp(Path, "/") == 0)
  146. sprintf(Filename, "/%s", dirent->d_name);
  147. else
  148. sprintf(Filename, "%s/%s", Path, dirent->d_name);
  149. fprintf(client_sock, "<tr>");
  150. len = strlen(dirroot) + strlen(Filename) + 1;
  151. realFilename = (char *)malloc(len + 1);
  152. bzero(realFilename, len + 1);
  153. sprintf(realFilename, "%s/%s", dirroot, Filename);
  154. if (stat(realFilename, &info) == 0) {
  155. if (strcmp(dirent->d_name, "..") == 0)
  156. fprintf(client_sock,
  157. "<td><a href=\"http://%s%s%s\">(parent)</a></td>",
  158. host, atoi(port) == 80 ? "" : nport,
  159. dir_up(Path));
  160. else
  161. fprintf(client_sock,
  162. "<td><a href=\"http://%s%s%s\">%s</a></td>",
  163. host, atoi(port) == 80 ? "" : nport, Filename,
  164. dirent->d_name);
  165. if (S_ISDIR(info.st_mode))
  166. fprintf(client_sock, "<td>目录</td>");
  167. else if (S_ISREG(info.st_mode))
  168. fprintf(client_sock, "<td>%d</td>", info.st_size);
  169. else if (S_ISLNK(info.st_mode))
  170. fprintf(client_sock, "<td>链接</td>");
  171. else if (S_ISCHR(info.st_mode))
  172. fprintf(client_sock, "<td>字符设备</td>");
  173. else if (S_ISBLK(info.st_mode))
  174. fprintf(client_sock, "<td>块设备</td>");
  175. else if (S_ISFIFO(info.st_mode))
  176. fprintf(client_sock, "<td>FIFO</td>");
  177. else if (S_ISSOCK(info.st_mode))
  178. fprintf(client_sock, "<td>Socket</td>");
  179. else
  180. fprintf(client_sock, "<td>(未知)</td>");
  181. fprintf(client_sock, "<td>%s</td>", ctime(&info.st_ctime));
  182. }
  183. fprintf(client_sock, "</tr>\n");
  184. free(realFilename);
  185. }
  186. fprintf(client_sock, "</table></center></body></html>");
  187. } else {
  188. /* 既非常规文件又非目录,禁止访问 */
  189. fprintf(client_sock,
  190. "HTTP/1.1 200 OK\r\nServer: DAS by Centos\r\nConnection: close\r\n\r\n"
  191. "<html>"
  192. "<meta charset=\"UTF-8\"/>"
  193. "<head><title>permission denied</title></head>"
  194. "<body><font size=+4>Linux下目录访问服务器</font><br><hr width=\"100%%\"><br><center>"
  195. "<table border cols=3 width=\"100%%\">");
  196. fprintf(client_sock,
  197. "</table><font color=\"CC0000\" size=+2>你访问的资源'%s'被禁止访问,请联系管理员解决!</font></body></html>",
  198. Path);
  199. }
  200. out:
  201. free(realPath);
  202. free(nport);
  203. }
  204. /*------------------------------------------------------
  205. *--- getoption - 分析取出程序的参数
  206. *------------------------------------------------------
  207. */
  208. void getoption(int argc, char **argv)
  209. {
  210. //    int c, len;
  211. //    char *p = 0;
  212. //
  213. //    opterr = 0;
  214. //    while (1) {
  215. //        int option_index = 0;
  216. //        static struct option long_options[] = {
  217. //            {"host", 1, 0, 0},
  218. //            {"port", 1, 0, 0},
  219. //            {"back", 1, 0, 0},
  220. //            {"dir", 1, 0, 0},
  221. //            {"log", 1, 0, 0},
  222. //            {"daemon", 0, 0, 0},
  223. //            {0, 0, 0, 0}
  224. //        };
  225. //        /* 本程序支持如一些参数:
  226. //         * --host IP地址 或者 -H IP地址
  227. //         * --port 端口 或者 -P 端口
  228. //         * --back 监听数量 或者 -B 监听数量
  229. //         * --dir 网站根目录 或者 -D 网站根目录
  230. //         * --log 日志存放路径 或者 -L 日志存放路径
  231. //         * --daemon 使程序进入后台运行模式
  232. //         */
  233. //        c = getopt_long(argc, argv, "H:P:B:D:L",
  234. //                        long_options, &option_index);
  235. //        if (c == -1 || c == '?')
  236. //            break;
  237. //
  238. //        if(optarg)        len = strlen(optarg);
  239. //        else        len = 0;
  240. //
  241. //        if ((!c && !(strcasecmp(long_options[option_index].name, "host")))
  242. //            || c == 'H')
  243. //            p = host = malloc(len + 1);
  244. //        else if ((!c
  245. //                  &&
  246. //                  !(strcasecmp(long_options[option_index].name, "port")))
  247. //                 || c == 'P')
  248. //            p = port = malloc(len + 1);
  249. //        else if ((!c
  250. //                  &&
  251. //                  !(strcasecmp(long_options[option_index].name, "back")))
  252. //                 || c == 'B')
  253. //            p = back = malloc(len + 1);
  254. //        else if ((!c
  255. //                  && !(strcasecmp(long_options[option_index].name, "dir")))
  256. //                 || c == 'D')
  257. //            p = dirroot = malloc(len + 1);
  258. //        else if ((!c
  259. //                  && !(strcasecmp(long_options[option_index].name, "log")))
  260. //                 || c == 'L')
  261. //            p = logdir = malloc(len + 1);
  262. //        else if ((!c
  263. //                  &&
  264. //                  !(strcasecmp
  265. //                    (long_options[option_index].name, "daemon")))) {
  266. //            daemon_y_n = 1;
  267. //            continue;
  268. //        }
  269. //        else
  270. //            break;
  271. //        bzero(p, len + 1);
  272. //        memcpy(p, optarg, len);
  273. //    }
  274. }
  275. int main(int argc, char **argv)
  276. {
  277. struct sockaddr_in addr;
  278. int sock_fd, addrlen;
  279. /* 获得程序工作的参数,如 IP 、端口、监听数、网页根目录、目录存放位置等 */
  280. //getoption(argc, argv);
  281. if (!host) {
  282. addrlen = strlen(DEFAULTIP);
  283. AllocateMemory(&host, addrlen, DEFAULTIP);
  284. }
  285. if (!port) {
  286. addrlen = strlen(DEFAULTPORT);
  287. AllocateMemory(&port, addrlen, DEFAULTPORT);
  288. }
  289. if (!back) {
  290. addrlen = strlen(DEFAULTBACK);
  291. AllocateMemory(&back, addrlen, DEFAULTBACK);
  292. }
  293. if (!dirroot) {
  294. addrlen = strlen(DEFAULTDIR);
  295. AllocateMemory(&dirroot, addrlen, DEFAULTDIR);
  296. }
  297. if (!logdir) {
  298. addrlen = strlen(DEFAULTLOG);
  299. AllocateMemory(&logdir, addrlen, DEFAULTLOG);
  300. }
  301. printf
  302. ("host=%s port=%s back=%s dirroot=%s logdir=%s %s是后台工作模式(进程ID:%d)\n",
  303. host, port, back, dirroot, logdir, daemon_y_n?"":"不", getpid());
  304. /* fork() 两次处于后台工作模式下 */
  305. if (daemon_y_n) {
  306. if (fork())
  307. exit(0);
  308. if (fork())
  309. exit(0);
  310. close(0), close(1), close(2);
  311. logfp = fopen(logdir, "a+");
  312. if (!logfp)
  313. exit(0);
  314. }
  315. /* 处理子进程退出以免产生僵尸进程 */
  316. signal(SIGCHLD, SIG_IGN);
  317. /* 创建 socket */
  318. if ((sock_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
  319. if (!daemon_y_n) {
  320. prterrmsg("socket()");
  321. } else {
  322. wrterrmsg("socket()");
  323. }
  324. }
  325. /* 设置端口快速重用 */
  326. addrlen = 1;
  327. setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &addrlen,
  328. sizeof(addrlen));
  329. addr.sin_family = AF_INET;
  330. addr.sin_port = htons(atoi(port));
  331. addr.sin_addr.s_addr = htonl(INADDR_ANY);//htonl(INADDR_ANY);
  332. addrlen = sizeof(struct sockaddr_in);
  333. /* 绑定地址、端口等信息 */
  334. if (bind(sock_fd, (struct sockaddr *) &addr, addrlen) < 0) {
  335. if (!daemon_y_n) {
  336. prterrmsg("bind()");
  337. } else {
  338. wrterrmsg("bind()");
  339. }
  340. }
  341. /* 开启临听 */
  342. if (listen(sock_fd, atoi(back)) < 0) {
  343. if (!daemon_y_n) {
  344. prterrmsg("listen()");
  345. } else {
  346. wrterrmsg("listen()");
  347. }
  348. }
  349. while (1) {
  350. int len;
  351. int new_fd;
  352. addrlen = sizeof(struct sockaddr_in);
  353. /* 接受新连接请求 */
  354. new_fd = accept(sock_fd, (struct sockaddr *) &addr, (socklen_t *)&addrlen);
  355. if (new_fd < 0) {
  356. if (!daemon_y_n) {
  357. prterrmsg("accept()");
  358. } else {
  359. wrterrmsg("accept()");
  360. }
  361. break;
  362. }
  363. bzero(buffer, MAXBUF + 1);
  364. sprintf(buffer, "连接来自于: %s:%d\n",
  365. inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
  366. if (!daemon_y_n) {
  367. prtinfomsg(buffer);
  368. } else {
  369. wrtinfomsg(buffer);
  370. }
  371. /* 产生一个子进程去处理请求,当前进程继续等待新的连接到来 */
  372. if (!fork()) {
  373. bzero(buffer, MAXBUF + 1);
  374. puts("recving...");
  375. if ((len = recv(new_fd, buffer, MAXBUF, 0)) > 0) {
  376. FILE *ClientFP = fdopen(new_fd, "w");
  377. if (ClientFP == NULL) {
  378. if (!daemon_y_n) {
  379. prterrmsg("fdopen()");
  380. } else {
  381. prterrmsg("fdopen()");
  382. }
  383. } else {
  384. char Req[MAXPATH + 1] = "";
  385. sscanf(buffer, "GET %s HTTP", Req);
  386. bzero(buffer, MAXBUF + 1);
  387. sprintf(buffer, "请求取文件: \"%s\"\n", Req);
  388. if (!daemon_y_n) {
  389. prtinfomsg(buffer);
  390. } else {
  391. wrtinfomsg(buffer);
  392. }
  393. /* 处理用户请求 */
  394. GiveResponse(ClientFP, Req);
  395. fclose(ClientFP);
  396. }
  397. }
  398. puts("go out");
  399. exit(0);
  400. }
  401. close(new_fd);
  402. }
  403. close(sock_fd);
  404. return 0;
  405. }

(2)编译运行(浏览器为客户端):

[html] view plaincopy
  1. gcc -o server server.c
  2. ./server

服务器运行:
在浏览器中输入:http://127.0.0.1:4040

注:需建立/tmp/http/dir和/tmp/http/log文件夹,并在dir下建立目录树。

然后在浏览器中点击文件即可下载文件,点击目录可进一步进行查看。点击parent可以返回到上一级目录。
(3)http客户端client.c(从服务器上下载文件并重新命名)

[html] view plaincopy
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <netdb.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <sys/socketvar.h>
  7. #include <strings.h>
  8. #include <arpa/inet.h>
  9. #include <unistd.h>
  10. #include <string.h>
  11. #include<errno.h>
  12. int main(int argc, char *argv[])
  13. {
  14. char buffer[1024] = {0};
  15. char host_addr[256] = {0};
  16. char host_file[256] = {0};
  17. char local_file[256] = {0};
  18. int sockfd;
  19. int send, totalsend;
  20. int nbytes;
  21. char request[1024] = {0};
  22. struct sockaddr_in server_addr;
  23. struct hostent *host;
  24. if (argc != 2) {
  25. fprintf(stderr, "Usage:%s web-address!\n", argv[0]);
  26. exit(1);
  27. }
  28. int portnumber = 4040;
  29. strcpy(host_addr, argv[1]);
  30. strcpy(host_file, "server.c");
  31. if ((host = gethostbyname(argv[1])) == NULL) {
  32. fprintf(stderr,"Gethostname error\n", strerror(errno));
  33. exit(1);
  34. }
  35. char ip_str[32] = {0};
  36. printf("address: %s\n", inet_ntop(host->h_addrtype, host->h_addr, ip_str, sizeof(ip_str)));
  37. if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  38. fprintf(stderr,"Socket Error:%s!\n",strerror(errno));
  39. exit(1);
  40. }
  41. bzero(&server_addr, sizeof(server_addr));
  42. server_addr.sin_family = AF_INET;
  43. server_addr.sin_port = htons(portnumber);
  44. server_addr.sin_addr = *((struct in_addr *)host->h_addr);
  45. if (connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1) {
  46. fprintf(stderr,"Connect Error:%s!\n",strerror(errno));
  47. exit(1);
  48. }
  49. sprintf(request, "GET /%s HTTP/1.1\r\nAccept: */*\r\nAccept-Language: zh-cn\r\n  \
  50. User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\r\n  \
  51. Host: %s:%d\r\nConnection: Close\r\n\r\n", host_file, host_addr, portnumber);
  52. strcpy(local_file, "local.txt");
  53. send = 0;
  54. totalsend = 0;
  55. nbytes = strlen(request);
  56. while (totalsend < nbytes) {
  57. send = write(sockfd, request + totalsend, nbytes - totalsend);
  58. if (send == -1) {
  59. printf("send error:%s!\n", strerror(errno));
  60. exit(0);
  61. }
  62. totalsend += send;
  63. printf("%d bytes send OK!\n", totalsend);
  64. }
  65. FILE * fp = fopen(local_file, "a");
  66. if(!fp) {
  67. printf("create file error:%s!\n", strerror(errno));
  68. return 0;
  69. }
  70. //printf("The following is the response header:\n");
  71. int i = 0;
  72. /* 连接成功了,接收http响应,response */
  73. while((nbytes = read(sockfd, buffer, 1)) == 1) {
  74. if (i < 4) {
  75. if (buffer[0] == '\r' || buffer[0] == '\n')
  76. i++;
  77. else
  78. i = 0;
  79. //printf("%c", buffer[0]);
  80. }
  81. else {
  82. fwrite(buffer, 1, 1, fp);/*将http主体信息写入文件*/
  83. //printf("%c", buffer[0]);
  84. i++;
  85. if(i % 1024 == 0)
  86. fflush(fp);   /**每1K时存盘一次**/
  87. }
  88. }
  89. printf("\n");
  90. fclose(fp);
  91. /* 结束通讯 */
  92. close(sockfd);
  93. return 0;
  94. }


在客户端程序的当前的目录下下载了local.txt,其中的内容是服务器上server.c文件的内容。

三、总结

(1)上述代码在centos上测试通过,只是功能实现,代码执行效率暂未考虑。
(2)若有建议,请留言,在此先感谢!

linux下c/c++实例之十socket简单应用相关推荐

  1. linux下c/c++实例之十四c实现的bt软件下载

    转载之http://m.blog.csdn.net/taiyang1987912/article/details/51288661

  2. Linux下安装Weblogic10.3.6并创建简单集群测试

    Linux下安装Weblogic10.3.6并创建简单集群进行测试 一.卸载随系统安装的openjdk 1.先查看安装的jdk信息,常用命令有rpm -qa | grep java, rpm -qa  ...

  3. G++ 4.4.7 无法编译模板程序,Vs可以,和解?智者尾部留言,本人第一次使用vs pro,通常并且习惯在linux下写些小东西,虽然程序简单;...

    G++ 4.4.7 无法编译模板程序,Vs可以,和解?智者尾部留言,本人第一次使用vs pro,通常并且习惯在linux下写些小东西,虽然程序简单; vs 模板编译运行Ok \ linux g++ 4 ...

  4. linux下c/c++实例之socket服务器实例

    一.简介 二.详解 简单socket服务器和客户端(基础) 服务器: /* * socket简单编程 服务端*/#include <stdio.h> #include <string ...

  5. Linux下删除mysql实例,linux下完全删除mysql

    在linux下开发,mysql数据库是经常用到的,对于初学者来说,在linux怎么安装卸载mysql数据库,也许可能比较痛苦,这里简单介绍下,怎么卸载msql数据库. a)查看系统中是否以rpm包安装 ...

  6. Linux下常用的C/C++开源Socket库

    1.      Linux Socket Programming In C++ : http://tldp.org/LDP/LG/issue74/tougher.html 2.      ACE: h ...

  7. linux数据库实例开机启动不了,linux下Oracle数据库实例开机自启动设置

    linux下数据库实例开机自启动设置 1.改动/oratab [root@org54 ~]# vi/etc/oratab     --把N改为Y,例如以下提示 # This file is used ...

  8. oracle的product删除不了,Linux下删除Oracle实例

    前两天远程重建Oracle实例过程中遇到的问题,记录如下: 1.vnc遭遇常见错误 [root@db1 bdump]# vncserver You will require a password to ...

  9. linux下python编程实例_python实现linux下使用xcopy的方法

    本文实例讲述了python实现linux下使用xcopy的方法.分享给大家供大家参考.具体如下: 这个python函数模仿windows下的xcopy命令编写,可以用在linux下 #!/usr/bi ...

最新文章

  1. HTML5新元素section和article的区别详解
  2. 为什么我在gpu上训练模型但是gpu利用率为0且运行速度还是很慢?
  3. Android解决NDK not configured问题
  4. [Windows]Windows路径探究
  5. php单屏网站源码,关于原生js实现类似fullpage的单页/全屏滚动的方法
  6. bzoj1078【SCOI2008】斜堆
  7. 怎样更好地使用快捷键?
  8. 什么是长连接和短连接?(长链接、短链接)什么时候使用长连接、短链接?
  9. 线性表的顺序存储结构(数据结构篇)
  10. 实战~阿里神器 Seata 实现 TCC模式 解决分布式事务,真香
  11. 导入开源的文件云存储平台-Seafile
  12. python中求众数_Python实现求众数的三种方法
  13. 【生活感想】期末考试
  14. vue通过自定义指令 v-py 将名字转拼音
  15. Python 基础:04 容器类型
  16. hfds下的文件导入hive表格
  17. 一、降维——机器学习笔记——降维(特征提取)
  18. vue使用支付宝支付
  19. C语言:for循环用法 完全攻略
  20. hackthebox-Toxic writeup

热门文章

  1. PHP中cookie和session的区别
  2. SCREEN屏幕编程时候必须保证SCREN中词典的字段格式必须和数据表中字段的类型长度一致!...
  3. iOS开发 之 可穿戴设备 蓝牙4.0 BLE 开发
  4. python基础学习1-三元表达式和lambda表达式
  5. bmp调色板颜色信息重复_如何更改 Linux 终端颜色主题 | Linux 中国
  6. wps表格粗线和细线区别_详解论文中的表格技术
  7. python import 类 继承_python学习之类的继承
  8. linux内核删不掉,linux 删除内核文件,未能启动,修复方法 CDROM与网络法
  9. linux伙伴系统算法,Linux伙伴系统(三)--分配
  10. 标题 计算机构自由度时主要步骤有哪些,2010年1月全国自考混凝土结构设计试题和答案...