You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

tcp_server.cpp 4.6 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #include <fcntl.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <errno.h>
  5. #include <stdio.h>
  6. #include <netinet/in.h>
  7. #include <resolv.h>
  8. #include <sys/socket.h>
  9. #include <arpa/inet.h>
  10. #include <unistd.h>
  11. #include <pthread.h>
  12. #include "message.pb.h"
  13. #include <iostream>
  14. #include <google/protobuf/io/coded_stream.h>
  15. #include <google/protobuf/io/zero_copy_stream_impl.h>
  16. using namespace std;
  17. using namespace google::protobuf::io;
  18. void *SocketHandler(void *);
  19. int main(int argv, char **argc)
  20. {
  21. int host_port = 1101;
  22. struct sockaddr_in my_addr;
  23. int hsock;
  24. int *p_int;
  25. int err;
  26. socklen_t addr_size = 0;
  27. int *csock;
  28. sockaddr_in sadr;
  29. pthread_t thread_id = 0;
  30. hsock = socket(AF_INET, SOCK_STREAM, 0);
  31. if (hsock == -1)
  32. {
  33. printf("Error initializing socket %d\n", errno);
  34. goto FINISH;
  35. }
  36. p_int = (int *)malloc(sizeof(int));
  37. *p_int = 1;
  38. if ((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char *)p_int, sizeof(int)) == -1) ||
  39. (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char *)p_int, sizeof(int)) == -1))
  40. {
  41. printf("Error setting options %d\n", errno);
  42. free(p_int);
  43. goto FINISH;
  44. }
  45. free(p_int);
  46. my_addr.sin_family = AF_INET;
  47. my_addr.sin_port = htons(host_port);
  48. memset(&(my_addr.sin_zero), 0, 8);
  49. my_addr.sin_addr.s_addr = INADDR_ANY;
  50. if (bind(hsock, (sockaddr *)&my_addr, sizeof(my_addr)) == -1)
  51. {
  52. fprintf(stderr, "Error binding to socket, make sure nothing else is listening on this port %d\n", errno);
  53. goto FINISH;
  54. }
  55. if (listen(hsock, 10) == -1)
  56. {
  57. fprintf(stderr, "Error listening %d\n", errno);
  58. goto FINISH;
  59. }
  60. //Now lets do the server stuff
  61. addr_size = sizeof(sockaddr_in);
  62. while (true)
  63. {
  64. printf("waiting for a connection\n");
  65. csock = (int *)malloc(sizeof(int));
  66. if ((*csock = accept(hsock, (sockaddr *)&sadr, &addr_size)) != -1)
  67. {
  68. printf("---------------------\nReceived connection from %s\n", inet_ntoa(sadr.sin_addr));
  69. pthread_create(&thread_id, 0, &SocketHandler, (void *)csock);
  70. pthread_detach(thread_id);
  71. }
  72. else
  73. {
  74. fprintf(stderr, "Error accepting %d\n", errno);
  75. }
  76. }
  77. FINISH:; //oops
  78. }
  79. google::protobuf::uint32 readHdr(char *buf)
  80. {
  81. google::protobuf::uint32 size;
  82. google::protobuf::io::ArrayInputStream ais(buf, 4);
  83. CodedInputStream coded_input(&ais);
  84. coded_input.ReadVarint32(&size); //Decode the HDR and get the size
  85. cout << "size of payload is " << size << endl;
  86. return size;
  87. }
  88. void readBody(int csock, google::protobuf::uint32 siz)
  89. {
  90. int bytecount;
  91. log_packet payload;
  92. char buffer[siz + 4]; //size of the payload and hdr
  93. //Read the entire buffer including the hdr
  94. if ((bytecount = recv(csock, (void *)buffer, 4 + siz, MSG_WAITALL)) == -1)
  95. {
  96. fprintf(stderr, "Error receiving data %d\n", errno);
  97. }
  98. cout << "Second read byte count is " << bytecount << endl;
  99. //Assign ArrayInputStream with enough memory
  100. google::protobuf::io::ArrayInputStream ais(buffer, siz + 4);
  101. CodedInputStream coded_input(&ais);
  102. //Read an unsigned integer with Varint encoding, truncating to 32 bits.
  103. coded_input.ReadVarint32(&siz);
  104. //After the message's length is read, PushLimit() is used to prevent the CodedInputStream
  105. //from reading beyond that length.Limits are used when parsing length-delimited
  106. //embedded messages
  107. google::protobuf::io::CodedInputStream::Limit msgLimit = coded_input.PushLimit(siz);
  108. //De-Serialize
  109. payload.ParseFromCodedStream(&coded_input);
  110. //Once the embedded message has been parsed, PopLimit() is called to undo the limit
  111. coded_input.PopLimit(msgLimit);
  112. //Print the message
  113. cout << "Message is " << payload.DebugString();
  114. }
  115. void *SocketHandler(void *lp)
  116. {
  117. int *csock = (int *)lp;
  118. char buffer[4];
  119. int bytecount = 0;
  120. string output, pl;
  121. log_packet logp;
  122. memset(buffer, '\0', 4);
  123. while (1)
  124. {
  125. //Peek into the socket and get the packet size
  126. if ((bytecount = recv(*csock,
  127. buffer,
  128. 4, MSG_PEEK)) == -1)
  129. {
  130. fprintf(stderr, "Error receiving data %d\n", errno);
  131. }
  132. else if (bytecount == 0)
  133. break;
  134. cout << "First read byte count is " << bytecount << endl;
  135. readBody(*csock, readHdr(buffer));
  136. }
  137. FINISH:
  138. free(csock);
  139. return 0;
  140. }