您的位置:首页 > 理论基础 > 计算机网络

TCP服务器的几种实现方式

2018-03-05 14:30 302 查看

1.简介

2.TCP客户端

#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>
using namespace std;

int main() {
//Create a socket For client to use TCP connect the Server
int fd = socket(AF_INET,SOCK_STREAM,0);
if(fd == -1) {
perror("Cannot Create a socket for TCP");
exit(EXIT_FAILURE);
}

//Set the client IP address and port
struct sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(0);
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(client_addr.sin_zero,0,8);

//Bind the socket with IP address and port
if(bind(fd,reinterpret_cast<sockaddr *>(&client_addr),sizeof(client_addr)) == -1) {
perror("Cannot bind the socket");
exit(EXIT_FAILURE);
}

//Set the Server IP address and port
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(23333);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(server_addr.sin_zero,0,8);

//Try to Connect the server
if(connect(fd,reinterpret_cast<sockaddr *>(&server_addr),sizeof(server_addr)) == -1) {
perror("Cannot connect the server");
exit(EXIT_FAILURE);
}
while(true) {
string buf;
cin >> buf;
if(buf == "stop")
break;
if(write(fd,buf.c_str(),buf.length()) != buf.length()) {
perror("Something Wrong when write");
exit(EXIT_FAILURE);
}
}
close(fd);
}


3. TCP服务器

#include <iostream>
#include <set>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/epoll.h>
using namespace std;

int main() {
//Create the server listen socket
int listen_fd = socket(AF_INET,SOCK_STREAM,0);
if(listen_fd == -1) {
perror("Cannot Create a Socket For TCP");
exit(EXIT_FAILURE);
}

//Set the Server IP Address and port
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(23333);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
memset(server_addr.sin_zero,0,8);

//Set the socket option with reuse address,Otherwise we cannot bind immediately after reboot
int is_reuse = 1;
if(setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,&is_reuse,sizeof(int)) == -1) {
perror("Cannot Set socket option");
exit(EXIT_FAILURE);
}

// //Bind the socket with IP address and port
if(bind(listen_fd,reinterpret_cast<sockaddr *>(&server_addr),sizeof(server_addr)) == -1) {
perror("Cannot Bind the socket");
exit(EXIT_FAILURE);
}

//Start to listen in this socket
if(listen(listen_fd,5) == -1) {
perror("Cannot use the socket to listen");
exit(EXIT_FAILURE);
}

//Save the connected client information
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);

//Server1:serial way,blocked IO,Interact with one client per time
// while(true) {
//  char buf[1024];
//  int connect_fd;
//  if((connect_fd = accept(listen_fd,reinterpret_cast<sockaddr *>(&client_addr),&length)) == -1) {
//      perror("Cannot get a TCP connection");
//      continue;
//  }
//  int n;
//  while(n = read(connect_fd,buf,1024)) {
//      if(n == -1) {
//          perror("Error when read Data:");
//          break;
//      } else {
//          memset(buf+n,0,1024-n);
//          char addr_ip[INET_ADDRSTRLEN];
//          inet_ntop(AF_INET,&client_addr.sin_addr,addr_ip,sizeof(addr_ip));
//          fprintf(stderr, "Receive data from:%s:%d,%s\n", addr_ip,ntohs(client_addr.sin_port),buf);
//      }
//  }
// }
// close(listen_fd);

//Server2:serial,IO multiplexing with select,per second to choose an active socket to handle
// fd_set read_fds;
// FD_ZERO(&read_fds);
// set<int> all_fd;
// all_fd.insert(listen_fd);
// while(true) {
//  struct timeval timeout = {1,0}; //select would change timeout value each time,we should reset it.
//  for(auto it = all_fd.begin();it != all_fd.end();it++) { //select would change timeout value each time, we should reset it too.
//      FD_SET(*it,&read_fds);
//  }
//  int result = select(*(all_fd.rbegin())+1,&read_fds,NULL,NULL,&timeout); //Blocked here until timeout or some socket can read
//  if(result == -1) {
//      perror("IO Error:");
//      continue;
//  } else if(result == 0) {
//      continue;
//  }
//  if(FD_ISSET(listen_fd,&read_fds)) {
//      int connect_fd;
//      if((connect_fd = accept(listen_fd,reinterpret_cast<sockaddr *>(&client_addr),&length)) == -1) { //would not block now,because it is ready.
//          perror("Cannot get a TCP connection");
//          continue;
//      }
//      char addr_ip[INET_ADDRSTRLEN];
//      inet_ntop(AF_INET,&client_addr.sin_addr,addr_ip,sizeof(addr_ip));
//      printf("Client %s:%d has connected to server\n",addr_ip,ntohs(client_addr.sin_port));
//      FD_SET(connect_fd,&read_fds); //Add the new connect_fd monitored by select
//      all_fd.insert(connect_fd);
//      FD_CLR(connect_fd,&read_fds); //Clear the new connect_fd
//      FD_CLR(listen_fd,&read_fds); //Clear the listen_fd after handle it
//  }
//  char buf[1024];
//  for(auto it = all_fd.begin();it != all_fd.end();++it) {
//      if(FD_ISSET(*it,&read_fds)) {
//          int n = read(*it,buf,1024);
//          char addr_ip[INET_ADDRSTRLEN];
//          getpeername(*it,reinterpret_cast<sockaddr *>(&client_addr),&length); //Get the peer address by fd
//          inet_ntop(AF_INET,&client_addr.sin_addr,addr_ip,sizeof(addr_ip));
//          if(n == -1 || n == 0) {
//              if(n == -1)
//                  perror("Error when read Data:");
//              else
//                  printf("Client %s:%d has closed the connection\n",addr_ip,ntohs(client_addr.sin_port));
//              close(*it);
//              all_fd.erase(it);
//          } else {
//              memset(buf+n,0,1024-n);

//              fprintf(stderr, "Receive data from:%s:%d,%s\n", addr_ip,ntohs(client_addr.sin_port),buf);
//          }
//          FD_CLR(*it,&read_fds);
//      }
//  }
// }
// close(listen_fd);

//server3:serial,IO multiplexing with epoll(More effective way),per second to choose an active socket to handle
int epoll_fd = epoll_create(1); //size is ignored in new version,simply set one positve interger is ok
if(epoll_fd == -1) {
perror("Cannot create epoll instance");
exit(EXIT_FAILURE);
}
int max_events = 20;
struct epoll_event listen_event;
struct epoll_event event_list[20];
listen_event.data.fd = listen_fd;
listen_event.events = EPOLLIN|EPOLLET; //Set the level triggered mode,

//If listenfd is ready,listen_event will be in event_list,we can check event_list to see either someone.data.fd is listen_fd.
if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,listen_fd,&listen_event) == -1) {
perror("Cannot add listen fd:");
exit(EXIT_FAILURE);
}

while(true) {
int result = epoll_wait(epoll_fd,event_list,max_events,1000);
if(result == -1) {
perror("IO Error:");
continue;
} else if(result == 0) {
continue;
}
char buf[1024];
for(int i = 0;i < result;i++) { //The ready fds is in events[0,result).data.fd
if(listen_fd == event_list[i].data.fd) {
int connect_fd = accept(listen_fd,reinterpret_cast<sockaddr *>(&client_addr),&length);
if(connect_fd == -1) {
perror("Cannot get a TCP connection");
continue;
}
char addr_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET,&client_addr.sin_addr,addr_ip,sizeof(addr_ip));
printf("Client %s:%d has connected to server\n",addr_ip,ntohs(client_addr.sin_port));
struct epoll_event read_event; //May debug here
read_event.data.fd = connect_fd;
read_event.events = EPOLLIN|EPOLLET;
epoll_ctl(epoll_fd,EPOLL_CTL_ADD,connect_fd,&read_event);
} else {
int connect_fd = event_list[i].data.fd;
int n = read(connect_fd,buf,1024);
getpeername(connect_fd,reinterpret_cast<sockaddr *>(&client_addr),&length); //Get the peer address by fd
char addr_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET,&client_addr.sin_addr,addr_ip,sizeof(addr_ip)); //Change the IP address into char *
if(n == -1 || n == 0) {
if(n == -1) {
perror("Error when read data");
} else {
printf("Client %s:%d has closed the connection\n",addr_ip,ntohs(client_addr.sin_port));
}
epoll_ctl(epoll_fd,EPOLL_CTL_DEL,connect_fd,NULL);
close(connect_fd);
continue;
}
memset(buf+n,0,1024-n);
printf("Receive data from %s:%d,%s\n", addr_ip,ntohs(client_addr.sin_port),buf);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: