socket-server.cpp

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <errno.h>
  5. #include <netinet/in.h>
  6. #include <arpa/inet.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <string.h>
  10. #include <string>
  11. #include <iostream>
  12. #include <climits>
  13. #define LENGTH 10
  14. #define SIZE 128
  15. struct socketaddr {
  16. unsigned short sa_family;
  17. char sa_data[14];
  18. };
  19. struct socketaddr_in {
  20. short int sin_family;
  21. unsigned short int sin_port;
  22. struct in_addr sin_addr;
  23. unsigned char sin_zero[8];
  24. };
  25. int String2int(char *str) {
  26. char flag = '+';
  27. long res = 0;
  28. if (*str == '-') {
  29. ++str; // 指针指向下一个
  30. flag = '-';
  31. }
  32. while (*str >= 48 && *str <= 57)
  33. {
  34. res = 10 * res + *str++ - 48;
  35. }
  36. if (flag == '-') {
  37. res = -res;
  38. }
  39. return (int) res;
  40. }
  41. int main(int argc, char **argv){
  42. using namespace std;
  43. // socketaddr addr;
  44. cout << "socket start" << endl;
  45. cout << "int size:" << sizeof(int) << endl;
  46. cout << "class socketaddr size:" << sizeof(socketaddr) << endl;
  47. cout << "class socketaddr_in size:" << sizeof(socketaddr_in) << endl;
  48. cout << "class in_addr size:" << sizeof(in_addr) << endl;
  49. int serv_port;
  50. if (argc != 2) {
  51. cout << "参数错误" << endl;
  52. exit(1);
  53. }
  54. serv_port = String2int(argv[1]);
  55. cout << "端口号:" << serv_port << endl;
  56. int res;
  57. int socketfd;
  58. int clientfd;
  59. struct socketaddr_in hostaddr;
  60. struct socketaddr_in clientaddr;
  61. unsigned int addrlen;
  62. char buf[SIZE];
  63. int cnt;
  64. cout << "创建服务器套接字 socket" << endl;
  65. cout << "AF_INET:" << AF_INET << endl;
  66. cout << "SOCK_STREAM:" << SOCK_STREAM << endl;
  67. socketfd = socket(AF_INET, SOCK_STREAM, 0);
  68. if (socketfd == -1) {
  69. cout << "创建服务器套接字失败" << endl;
  70. exit(1);
  71. }
  72. cout << "绑定协议号与端口号" << endl;
  73. hostaddr.sin_family = AF_INET;
  74. hostaddr.sin_port = htons(serv_port);
  75. cout << "本机IP地址" << INADDR_ANY << endl;
  76. hostaddr.sin_addr.s_addr = INADDR_ANY;
  77. bzero(&(hostaddr.sin_zero), 8);
  78. // 1.一个应用程序只能绑定一个端口(一个套接字只能绑定一个端口)
  79. // 2.UDP端口和TCP端口 虽然端口号相同,但是是不同的端口
  80. /*
  81. 3.病毒端口复用,是先断开原来的端口,然后自己连接上去,然后是自己的数据就自>己处理
  82. 不是自己的就分发给其他程序
  83. */
  84. // 4.可以多个线程同时receive你绑定的套接字,共享你绑定的套接字
  85. /*
  86. 5.设置端口复用
  87. SO_REUSEADDR可以用在以下4种情况下
  88. 5.1当有一个socket1处于TIME_WAIT状态时,而你启动的程序socket2需要用到该地址和端口,你的程序可以用到此项。
  89. 5.2SO_REUSEADDR允许同一个port上启动同一服务的多个实例(多个进程)。但每个>实例绑定的ip地址不能相同。有多块网卡或用IP Alias技术的机器可以测试这种情况。
  90. 5.3SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑>定的ip地址不同,这和5.2很相似,区别请看UNPv1
  91. 5.4SO_REUSEADDR允许完全相同的地址和端口绑定,但这只用于UDP的多播,不能用于TCP。
  92. 注意:设置端口复用函数要在绑定之前调用,而且只要绑定到同一个端口的所有套接字都得设置复用。
  93. */
  94. // int opt = 1;
  95. // setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
  96. res = bind(socketfd, (struct sockaddr *) &hostaddr, sizeof(struct sockaddr));
  97. if (res == -1) {
  98. cout << "套接字绑定失败" << endl;
  99. exit(1);
  100. }
  101. res = listen(socketfd, LENGTH);
  102. if (res == -1) {
  103. cout << "设置监听模式错误" << endl;
  104. exit(1);
  105. }
  106. cout << "等待客户端请求连接" << endl;
  107. while (1) {
  108. addrlen = sizeof(struct socketaddr_in);
  109. clientfd = accept(socketfd, (struct sockaddr *) &clientaddr, &addrlen);
  110. if (clientfd == -1) {
  111. cout << "接受连接请求错误" << endl;
  112. continue;
  113. }
  114. cout << "客户端 IP" << inet_ntoa(clientaddr.sin_addr) << endl;
  115. cnt = recv(clientfd, buf, SIZE, 0);
  116. if (cnt == -1) {
  117. cout << "数据接收失败" << endl;
  118. exit(1);
  119. }
  120. cout << buf << endl;
  121. close(clientfd);
  122. }
  123. return 0;
  124. }

socket-client.cpp

  1. #include <iostream>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <errno.h>
  6. #include <string.h>
  7. #include <string>
  8. #include <sys/socket.h>
  9. #include <sys/types.h>
  10. #include <netinet/in.h>
  11. #define SIZE 128
  12. struct socketaddr {
  13. unsigned short sa_family;
  14. char sa_data[14];
  15. };
  16. struct socketaddr_in {
  17. short int sin_family;
  18. unsigned short int sin_port;
  19. struct in_addr sin_addr;
  20. unsigned char sin_zero[8];
  21. };
  22. int String2int(char *str) {
  23. char flag = '+';
  24. long res = 0;
  25. if (*str == '-') {
  26. ++str; // 指针指向下一个
  27. flag = '-';
  28. }
  29. while (*str >= 48 && *str <= 57)
  30. {
  31. res = 10 * res + *str++ - 48;
  32. }
  33. if (flag == '-') {
  34. res = -res;
  35. }
  36. return (int) res;
  37. }
  38. int main(int argc, char **argv) {
  39. using namespace std;
  40. cout << argc << endl;
  41. cout << argv << endl;
  42. if (argc != 3) {
  43. cout << "参数错误" << endl;
  44. exit(1);
  45. }
  46. int res;
  47. int sockfd;
  48. struct socketaddr_in servaddr;
  49. char buf[SIZE];
  50. int cnt;
  51. int serv_port;
  52. serv_port = String2int(argv[1]);
  53. if (serv_port == 0) {
  54. cout << "端口错误" << endl;
  55. exit(1);
  56. }
  57. sockfd = socket(AF_INET, SOCK_STREAM, 0);
  58. if (sockfd == -1) {
  59. cout << "套接字创建失败" << endl;
  60. exit(1);
  61. }
  62. servaddr.sin_family = AF_INET;
  63. servaddr.sin_port = htons(serv_port);
  64. cout << "htons(...):" << htons(serv_port) << endl;
  65. servaddr.sin_addr.s_addr = INADDR_ANY;
  66. bzero(&(servaddr.sin_zero), 8);
  67. res = connect(sockfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr));
  68. if (res == -1) {
  69. cout << "连接失败" << endl;
  70. exit(1);
  71. }
  72. strcpy(buf, argv[2]);
  73. cnt = send(sockfd, buf, SIZE, 0);
  74. if (cnt == -1) {
  75. cout << "发送失败" << endl;
  76. exit(1);
  77. }
  78. cout << "发送数据:" << buf << endl;
  79. close(sockfd);
  80. return 0;
  81. }