TCP服务器的几种实现方式

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);
            }
        }
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Wiznet TCP服务器例程是一种基于Wiznet网络模块的网络编程示例。Wiznet是一家专门提供以太网连接解决方案的公司,他们的产品包括硬件模块和软件库,可以帮助用户快速构建基于以太网的网络应用。 在使用Wiznet TCP服务器例程前,首先需要将Wiznet硬件模块与目标设备连接,并进行相应的配置。配置过程包括初始化网络模块、设置IP地址、端口号等。 一旦配置完成,就可以开始编写TCP服务器的应用程序。TCP服务器的主要功能是监听指定的端口,接受客户端的连接请求,并与客户端进行数据交换。 在Wiznet TCP服务器例程中,主要包含以下几个环节: 1. 创建服务器套接字:通过调用相关函数创建服务器套接字,并指定监听的端口号。 2. 监听连接请求:使用套接字函数监听指定的端口,等待客户端的连接请求。 3. 接受客户端连接:一旦有客户端连接请求到达服务器服务器将会接受连接,并为该客户端创建一个独立的套接字。 4. 数据交换:服务器通过独立的套接字与客户端进行数据交换。可以发送数据给客户端,也可以接收来自客户端的数据。 5. 断开连接:当客户端与服务器的数据交换完成后,可以主动断开连接。服务器端也可以通过关闭套接字来断开与客户端的连接。 总结起来,Wiznet TCP服务器例程是一个示范如何使用Wiznet网络模块来构建TCP服务器的实例。通过这个例程,我们可以了解到如何配置网络模块和实现服务器端的功能,从而为我们的网络应用提供一个基础框架。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值