HTTP是基于IP/TCP加上了网络请求的固定格式, 比如:

  1. method
  2. URL
  3. Content-host
  4. Content-Type
  5. Content-Length

实现GET请求

把组合成的数据按照固定的格式发送给服务器, 服务器解析相应的格式, 然后返回服务器数据:

  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <sys/types.h>
  4. #include <time.h>
  5. #include <errno.h>
  6. #include <signal.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <sys/wait.h>
  11. #include <sys/time.h>
  12. #include <netinet/in.h>
  13. #include <arpa/inet.h>
  14. #define IPSTR "42.121.252.58" //服务器IP地址;
  15. #define PORT 80
  16. #define BUFSIZE 1024
  17. int main(int argc, char **argv)
  18. {
  19. int sockfd, ret, i, h;
  20. struct sockaddr_in servaddr;
  21. char str1[4096], str2[4096], buf[BUFSIZE], *str;
  22. socklen_t len;
  23. fd_set t_set1;
  24. struct timeval tv;
  25. //创建套接字
  26. if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
  27. printf("创建网络连接失败,本线程即将终止---socket error!\n");
  28. exit(0);
  29. };
  30. bzero(&servaddr, sizeof(servaddr));
  31. servaddr.sin_family = AF_INET;
  32. servaddr.sin_port = htons(PORT);
  33. if (inet_pton(AF_INET, IPSTR, &servaddr.sin_addr) <= 0 ){
  34. printf("创建网络连接失败,本线程即将终止--inet_pton error!\n");
  35. exit(0);
  36. };
  37. if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){
  38. printf("连接到服务器失败,connect error!\n");
  39. exit(0);
  40. }
  41. printf("与远端建立了连接\n");
  42. memset(str2, 0, 4096);
  43. strcat(str2, "theDataToPost");
  44. str=(char *)malloc(128);
  45. len = strlen(str2);
  46. sprintf(str, "%d", len);
  47. memset(str1, 0, 4096);
  48. strcat(str1, "GET /ymnets/p/6255674.html HTTP/1.1\n");
  49. strcat(str1, "Host: www.cnblogs.com\n");
  50. strcat(str1, "Content-Type: text/html\n");
  51. strcat(str1, "Content-Length: ");
  52. strcat(str1, str);
  53. strcat(str1, "\n\n");
  54. strcat(str1, str2);
  55. strcat(str1, "\r\n\r\n");
  56. printf("%s\n",str1);
  57. ret = write(sockfd,str1,strlen(str1));
  58. if (ret < 0) {
  59. printf("发送失败!错误代码是%d,错误信息是'%s'\n",errno, strerror(errno));
  60. exit(0);
  61. }else{
  62. printf("消息发送成功,共发送了%d个字节!\n\n", ret);
  63. }
  64. FD_ZERO(&t_set1);
  65. FD_SET(sockfd, &t_set1);
  66. while(1){
  67. sleep(2);
  68. tv.tv_sec= 0;
  69. tv.tv_usec= 0;
  70. h= 0;
  71. printf("--------------->1");
  72. h= select(sockfd +1, &t_set1, NULL, NULL, &tv);
  73. printf("--------------->2");
  74. //if (h == 0) continue;
  75. if (h < 0) {
  76. close(sockfd);
  77. printf("在读取数据报文时SELECT检测到异常,该异常导致线程终止!\n");
  78. return -1;
  79. };
  80. if (h > 0){
  81. memset(buf, 0, 4096);
  82. i= read(sockfd, buf, 4095);
  83. if (i==0){
  84. close(sockfd);
  85. printf("读取数据报文时发现远端关闭,该线程终止!\n");
  86. return -1;
  87. }
  88. printf("%s\n", buf);
  89. }
  90. }
  91. close(sockfd);
  92. return 0;
  93. }

实现POST请求

C实现POST请求参考代码, 只要把请求类型从GET改为POST, 然后把请求的数据代入到请求头中即可:

  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <sys/types.h>
  4. #include <time.h>
  5. #include <errno.h>
  6. #include <signal.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <sys/wait.h>
  11. #include <sys/time.h>
  12. #include <netinet/in.h>
  13. #include <arpa/inet.h>
  14. #define IPSTR "61.147.124.120"
  15. #define PORT 80
  16. #define BUFSIZE 1024
  17. int main(int argc, char **argv)
  18. {
  19. int sockfd, ret, i, h;
  20. struct sockaddr_in servaddr;
  21. char str1[4096], str2[4096], buf[BUFSIZE], *str;
  22. socklen_t len;
  23. fd_set t_set1;
  24. struct timeval tv;
  25. if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
  26. printf("创建网络连接失败,本线程即将终止---socket error!\n");
  27. exit(0);
  28. };
  29. bzero(&servaddr, sizeof(servaddr));
  30. servaddr.sin_family = AF_INET;
  31. servaddr.sin_port = htons(PORT);
  32. if (inet_pton(AF_INET, IPSTR, &servaddr.sin_addr) <= 0 ){
  33. printf("创建网络连接失败,本线程即将终止--inet_pton error!\n");
  34. exit(0);
  35. };
  36. if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){
  37. printf("连接到服务器失败,connect error!\n");
  38. exit(0);
  39. }
  40. printf("与远端建立了连接\n");
  41. memset(str2, 0, 4096);
  42. strcat(str2, "qqCode=287101329");
  43. str=(char *)malloc(128);
  44. len = strlen(str2);
  45. sprintf(str, "%d", len);
  46. memset(str1, 0, 4096);
  47. strcat(str1, "POST /webservices/qqOnlineWebService.asmx/qqCheckOnline HTTP/1.1\n");
  48. strcat(str1, "Host: www.webxml.com.cn\n");
  49. strcat(str1, "Content-Type: application/x-www-form-urlencoded\n");
  50. strcat(str1, "Content-Length: ");
  51. strcat(str1, str);
  52. strcat(str1, "\n\n");
  53. //str2的值为post的数据
  54. strcat(str1, str2);
  55. strcat(str1, "\r\n\r\n");
  56. printf("%s\n",str1);
  57. ret = write(sockfd,str1,strlen(str1));
  58. if (ret < 0) {
  59. printf("发送失败!错误代码是%d,错误信息是'%s'\n",errno, strerror(errno));
  60. exit(0);
  61. }else{
  62. printf("消息发送成功,共发送了%d个字节!\n\n", ret);
  63. }
  64. FD_ZERO(&t_set1);
  65. FD_SET(sockfd, &t_set1);
  66. while(1){
  67. sleep(2);
  68. tv.tv_sec= 0;
  69. tv.tv_usec= 0;
  70. h= 0;
  71. printf("--------------->1");
  72. h= select(sockfd +1, &t_set1, NULL, NULL, &tv);
  73. printf("--------------->2");
  74. //if (h == 0) continue;
  75. if (h < 0) {
  76. close(sockfd);
  77. printf("在读取数据报文时SELECT检测到异常,该异常导致线程终止!\n");
  78. return -1;
  79. };
  80. if (h > 0){
  81. memset(buf, 0, 4096);
  82. i= read(sockfd, buf, 4095);
  83. if (i==0){
  84. close(sockfd);
  85. printf("读取数据报文时发现远端关闭,该线程终止!\n");
  86. return -1;
  87. }
  88. printf("%s\n", buf);
  89. }
  90. }
  91. close(sockfd);
  92. return 0;
  93. }

POST请求的方式可以再改改:

  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <sys/types.h>
  4. #include <time.h>
  5. #include <errno.h>
  6. #include <signal.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <sys/wait.h>
  11. #include <sys/time.h>
  12. #include <netinet/in.h>
  13. #include <arpa/inet.h>
  14. #define IPSTR "61.147.124.120"
  15. #define PORT 80
  16. #define BUFSIZE 1024
  17. int main(int argc, char **argv)
  18. {
  19. int sockfd, ret, i, h;
  20. struct sockaddr_in servaddr;
  21. char str1[4096], str2[4096], buf[BUFSIZE], *str;
  22. socklen_t len;
  23. fd_set t_set1;
  24. struct timeval tv;
  25. if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
  26. printf("创建网络连接失败,本线程即将终止---socket error!\n");
  27. exit(0);
  28. };
  29. bzero(&servaddr, sizeof(servaddr));
  30. servaddr.sin_family = AF_INET;
  31. servaddr.sin_port = htons(PORT);
  32. if (inet_pton(AF_INET, IPSTR, &servaddr.sin_addr) <= 0 ){
  33. printf("创建网络连接失败,本线程即将终止--inet_pton error!\n");
  34. exit(0);
  35. };
  36. if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){
  37. printf("连接到服务器失败,connect error!\n");
  38. exit(0);
  39. }
  40. printf("与远端建立了连接\n");
  41. memset(str2, 0, 4096);
  42. strcat(str2, "qqCode=287101329");
  43. str=(char *)malloc(128);
  44. len = strlen(str2);
  45. sprintf(str, "%d", len);
  46. memset(str1, 0, 4096);
  47. strcat(str1, "POST /webservices/qqOnlineWebService.asmx/qqCheckOnline HTTP/1.1\n");
  48. strcat(str1, "Host: www.webxml.com.cn\n");
  49. strcat(str1, "Content-Type: application/x-www-form-urlencoded\n");
  50. strcat(str1, "Content-Length: ");
  51. strcat(str1, str);
  52. strcat(str1, "\n\n");
  53. //str2的值为post的数据
  54. strcat(str1, str2);
  55. strcat(str1, "\r\n\r\n");
  56. printf("%s\n",str1);
  57. ret = write(sockfd,str1,strlen(str1));
  58. if (ret < 0) {
  59. printf("发送失败!错误代码是%d,错误信息是'%s'\n",errno, strerror(errno));
  60. exit(0);
  61. }else{
  62. printf("消息发送成功,共发送了%d个字节!\n\n", ret);
  63. }
  64. FD_ZERO(&t_set1);
  65. FD_SET(sockfd, &t_set1);
  66. tv.tv_sec= 0;
  67. tv.tv_usec= 0;
  68. h= 0;
  69. while(1){
  70. sleep(2);
  71. printf("--------------->1");
  72. h = select(sockfd +1, &t_set1, NULL, NULL, &tv);
  73. printf("--------------->2");
  74. //if (h == 0) continue;
  75. if (h == -1) {
  76. close(sockfd);
  77. printf("在读取数据报文时SELECT检测到异常,该异常导致线程终止!\n");
  78. return -1;
  79. };
  80. if ( FD_ISSET(sockfd, &t_set1) ){
  81. memset(buf, 0, 4096);
  82. i= read(sockfd, buf, 4095);
  83. if (i==0){
  84. close(sockfd);
  85. printf("读取数据报文时发现远端关闭,该线程终止!\n");
  86. return -1;
  87. }
  88. printf("%s\n", buf);
  89. }
  90. }
  91. close(sockfd);
  92. return 0;
  93. }

请求一个HTTP服务器的数据, 接收一个参数为请求的服务器IP:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <arpa/inet.h>
  7. #include <netinet/in.h>
  8. #include <unistd.h>
  9. int main(int argc, char *argv[]){
  10. if(argc!=2){
  11. printf("error usage %s ip\n",argv[0]);
  12. return 1;
  13. }
  14. int sockfd;
  15. int len;
  16. struct sockaddr_in address;
  17. int result;
  18. char httpstring[100];
  19. sprintf(httpstring,"GET / HTTP/1.1\r\n"
  20. "Host: %s\r\n"
  21. "Connection: Close\r\n\r\n",argv[1]);
  22. char ch;
  23. sockfd = socket(AF_INET, SOCK_STREAM, 0);
  24. address.sin_family = AF_INET;
  25. address.sin_addr.s_addr = inet_addr(argv[1]);
  26. address.sin_port = htons(80);
  27. len = sizeof(address);
  28. result = connect(sockfd,(struct sockaddr *)&address,len);
  29. if(result == -1){
  30. perror("oops: client");
  31. return 1;
  32. }
  33. write(sockfd,httpstring,strlen(httpstring));
  34. while(read(sockfd,&ch,1)){
  35. printf("%c", ch);
  36. }
  37. close(sockfd);
  38. printf("\n");
  39. return 0;
  40. }