C语言服务器,多版本

  • t9_962685
    了解作者
  • 25.7KB
    文件大小
  • zip
    文件格式
  • 0
    收藏次数
  • VIP专享
    资源类型
  • 0
    下载次数
  • 2022-06-10 12:37
    上传日期
libuv(timer、isprime、sleep),socket服务器(blocking、epoll、nonblocking、select、sequential、threaded)
libuv-socket等多种服务器.zip
  • async-socket-server
  • select-server.c
    10KB
  • nonblocking-listener.c
    1.6KB
  • threadspammer.c
    1KB
  • server-test.py
    6.6KB
  • threadpool-server-coroutine.py
    2.6KB
  • uv-isprime-server.c
    8KB
  • uv-timer-sleep-demo.c
    729B
  • simple-client.py
    3KB
  • threaded-server.c
    2.8KB
  • epoll-server.c
    9.1KB
  • utils.c
    2.2KB
  • threadpool-server.py
    2KB
  • uv-server.c
    7.8KB
  • blocking-listener.c
    1.1KB
  • utils.h
    1.1KB
  • uv-timer-work-demo.c
    964B
  • Makefile
    1.9KB
  • sequential-server.c
    2.1KB
内容介绍
// Asynchronous socket server - accepting multiple clients concurrently, // multiplexing the connections with select. // // Eli Bendersky [http://eli.thegreenplace.net] // This code is in the public domain. #include <assert.h rel='nofollow' onclick='return false;'> #include <errno.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/select.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include "utils.h" // Note: FD_SETSIZE is 1024 on Linux, which is tricky to change. This provides a // natural limit to the number of simultaneous FDs monitored by select(). #define MAXFDS 1000 typedef enum { INITIAL_ACK, WAIT_FOR_MSG, IN_MSG } ProcessingState; #define SENDBUF_SIZE 1024 typedef struct { ProcessingState state; // sendbuf contains data the server has to send back to the client. The // on_peer_ready_recv handler populates this buffer, and on_peer_ready_send // drains it. sendbuf_end points to the last valid byte in the buffer, and // sendptr at the next byte to send. uint8_t sendbuf[SENDBUF_SIZE]; int sendbuf_end; int sendptr; } peer_state_t; // Each peer is globally identified by the file descriptor (fd) it's connected // on. As long as the peer is connected, the fd is unique to it. When a peer // disconnects, a new peer may connect and get the same fd. on_peer_connected // should initialize the state properly to remove any trace of the old peer on // the same fd. peer_state_t global_state[MAXFDS]; // Callbacks (on_XXX functions) return this status to the main loop; the status // instructs the loop about the next steps for the fd for which the callback was // invoked. // want_read=true means we want to keep monitoring this fd for reading. // want_write=true means we want to keep monitoring this fd for writing. // When both are false it means the fd is no longer needed and can be closed. typedef struct { bool want_read; bool want_write; } fd_status_t; // These constants make creating fd_status_t values less verbose. const fd_status_t fd_status_R = {.want_read = true, .want_write = false}; const fd_status_t fd_status_W = {.want_read = false, .want_write = true}; const fd_status_t fd_status_RW = {.want_read = true, .want_write = true}; const fd_status_t fd_status_NORW = {.want_read = false, .want_write = false}; fd_status_t on_peer_connected(int sockfd, const struct sockaddr_in* peer_addr, socklen_t peer_addr_len) { assert(sockfd < MAXFDs); report_peer_connected(peer_addr, peer_addr_len); // Initialize state to send back a '*' to the peer immediately. peer_state_t* peerstate = &global_state[sockfd]; peerstate->state = INITIAL_ACK; peerstate->sendbuf[0] = '*'; peerstate->sendptr = 0; peerstate->sendbuf_end = 1; // Signal that this socket is ready for writing now. return fd_status_W; } fd_status_t on_peer_ready_recv(int sockfd) { assert(sockfd < MAXFDs); peer_state_t* peerstate = &global_state[sockfd]; if (peerstate->state == INITIAL_ACK || peerstate->sendptr < peerstate->sendbuf_end) { // Until the initial ACK has been sent to the peer, there's nothing we // want to receive. Also, wait until all data staged for sending is sent to // receive more data. return fd_status_W; } uint8_t buf[1024]; int nbytes = recv(sockfd, buf, sizeof buf, 0); if (nbytes == 0) { // The peer disconnected. return fd_status_NORW; } else if (nbytes < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // The socket is not *really* ready for recv; wait until it is. return fd_status_R; } else { perror_die("recv"); } } bool ready_to_send = false; for (int i = 0; i < nbytes; ++i) { switch (peerstate->state) { case INITIAL_ACK: assert(0 && "can't reach here"); break; case WAIT_FOR_MSG: if (buf[i] == '^') { peerstate->state = IN_MSG; } break; case IN_MSG: if (buf[i] == '$') { peerstate->state = WAIT_FOR_MSG; } else { assert(peerstate->sendbuf_end < SENDBUF_SIZE); peerstate->sendbuf[peerstate->sendbuf_end++] = buf[i] + 1; ready_to_send = true; } break; } } // Report reading readiness iff there's nothing to send to the peer as a // result of the latest recv. return (fd_status_t){.want_read = !ready_to_send, .want_write = ready_to_send}; } fd_status_t on_peer_ready_send(int sockfd) { assert(sockfd < MAXFDs); peer_state_t* peerstate = &global_state[sockfd]; if (peerstate->sendptr >= peerstate->sendbuf_end) { // Nothing to send. return fd_status_RW; } int sendlen = peerstate->sendbuf_end - peerstate->sendptr; int nsent = send(sockfd, peerstate->sendbuf, sendlen, 0); if (nsent == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return fd_status_W; } else { perror_die("send"); } } if (nsent < sendlen) { peerstate->sendptr += nsent; return fd_status_W; } else { // Everything was sent successfully; reset the send queue. peerstate->sendptr = 0; peerstate->sendbuf_end = 0; // Special-case state transition in if we were in INITIAL_ACK until now. if (peerstate->state == INITIAL_ACK) { peerstate->state = WAIT_FOR_MSG; } return fd_status_R; } } int main(int argc, char** argv) { setvbuf(stdout, NULL, _IONBF, 0); int portnum = 9090; if (argc >= 2) { portnum = atoi(argv[1]); } printf("Serving on port %d\n", portnum); int listener_sockfd = listen_inet_socket(portnum); // The select() manpage warns that select() can return a read notification // for a socket that isn't actually readable. Thus using blocking I/O isn't // safe. make_socket_non_blocking(listener_sockfd); if (listener_sockfd >= FD_SETSIZE) { die("listener socket fd (%d) >= FD_SETSIZE (%d)", listener_sockfd, FD_SETSIZE); } // The "master" sets are owned by the loop, tracking which FDs we want to // monitor for reading and which FDs we want to monitor for writing. fd_set readfds_master; FD_ZERO(&readfds_master); fd_set writefds_master; FD_ZERO(&writefds_master); // The listenting socket is always monitored for read, to detect when new // peer connections are incoming. FD_SET(listener_sockfd, &readfds_master); // For more efficiency, fdset_max tracks the maximal FD seen so far; this // makes it unnecessary for select to iterate all the way to FD_SETSIZE on // every call. int fdset_max = listener_sockfd; while (1) { // select() modifies the fd_sets passed to it, so we have to pass in copies. fd_set readfds = readfds_master; fd_set writefds = writefds_master; int nready = select(fdset_max + 1, &readfds, &writefds, NULL, NULL); if (nready < 0) { perror_die("select"); } // nready tells us the total number of ready events; if one socket is both // readable and writable it will be 2. Therefore, it's decremented when // either a readable or a writable socket is encountered. for (int fd = 0; fd <= fdset_max && nready > 0; fd++) { // Check if this fd became readable. if (FD_ISSET(fd, &readfds)) { nready--; if (fd == listener_sockfd) { // The listening socket is ready; this means a new peer is connecting. struct sockaddr_in peer_addr; socklen_t peer_addr_len = sizeof(peer_addr); int newsockfd = accept(listener_sockfd, (struct sockaddr*)&peer_addr, &peer_addr_len); if (newsockfd < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // This can happen due to the nonblocking socket mode; in this // case don't
评论
    相关推荐
    • RTSP 服务器C语言
      RTSP是实时流媒体传输协议,服务器和客户端之间通过RTSP协议实现握手和认证过程,通过RTP协议传输视频数据包,本资源通过C语言实现了RTSP服务器的功能。
    • 最新仙镜传说服务器c语言源码
      最新的仙镜传说服务器C语言源码,这是日本最新在布的,数据库类型为文件型数据库。 这个源码相当的完整,只要编译一次后就可以运行了,但得用到客户端的两个文件一个是data.grf另一个是sdata.grf,大家都可以试试!...
    • 守护进程时间服务器C语言实现.rar
      守护进程时间服务器C语言实现,适合编程小白
    • 最新仙镜传说服务器C语言源码
      最新的仙镜传说服务器C语言源码,这是日本最新在布的,数据库类型为文件型数据库。 这个源码相当的完整,只要编译一次后就可以运行了,但得用到客户端的两个文件一个是data.grf另一个是sdata.grf,大家都可以试试!
    • RTSP服务器C语言
      hi3516A输出h264码流,rtsp服务器完成推流,环形缓冲,异步监测。
    • http代理服务器C语言
      以前上TCP/IP课程时做的课程设计,很小的一个HTTP代理服务器,基于socket编程。VC6.0环境的。原创程序。 那时候还是新手,程序很简陋,不过好歹能用。 学校学习相关课程的学生可以参考下,当个课程作业没问题,老手...
    • 最新仙镜传说服务器C语言源码
      最新的仙镜传说服务器C语言源码,这是日本最新在布的,数据库类型为文件型数据库。这个源码相当的完整,只要编译一次后就可以运行了,但得用到客户端的两个文件一个是data.grf另一个是sdata.grf,大家都可以试试!我...
    • 最新仙镜传说服务器C语言源码.zip
      最新仙镜传说服务器C语言源码.zip为游戏源代码,作为开发游戏的一个很好DEMO
    • web服务器 C语言
      一个用C语言编写的WEB服务器,用socket编程
    • C语言并发服务器
      C语言并发服务器,包括客户端和服务器端。