Linux下实现简单Echo中继服务器
来源:互联网 发布:java boolean几个字节 编辑:程序博客网 时间:2024/05/17 08:48
Linux下编写一个Echo中继服务器,echo客户端通过它获取Echo服务器的响应。中继服务器能同时作为多个echo服务器的中继,并且具有一个简单的负载均衡算法。
1. 服务器与客户端描述与设计
支持多个服务器进行Echo服务,服务器需要设定输入端口参数,服务器和客户端可以直接使用多进程版本的设计即可。
2. 中继服务器描述与设计
为了简化,假定所有的服务器都在相同的ip地址上,而使用不同的端口,中继服务器只需要一个ip和多个端口参数的输入。
当客户端连接时,中继服务器Accept之后,开启新的进程A,进程A向使用负载均衡算法找出的Echo服务器申请连接,连接成功之后,进程A创建工作线程P。进程A的主线程接收从客户端发来的信息并发给Echo服务器,工作线程P接收从Echo服务器发来的信息并发给客户端。
这样设计是为了当客户端退出时,能够关闭socket连接,正常退出程序。
对于中继服务器还需要考虑负载均衡的,现使用最简单的算法,即在中继服务器维护一个“下次连接服务器号”,每次有客户端连接,就使用这个号码找到应该连接的服务器,然后这个号加1。
3. 端口规定
中继服务器在9000端口监听客户端的连接;
服务器在给定的端口监听中继服务器的连接。
完整代码如下:
1. 中继器
// recpeater.c#include "unp.h" #define BUFFER_SIZE BUFFSIZE#define SERVPORT 9000#define BACKLOG 20 #define MAX_SERVER 10 char buffer_c[BUFFER_SIZE];char buffer_s[BUFFER_SIZE];int serAmount;int port[MAX_SERVER];int portCurrent;char *serIp; typedef struct m_socket { int s_server; int s_client;} m_socket, * pm_socket; void str_send_2_server(int s_server, int s_client, char* buf) { size_t n; while (1) { n = Read(s_client, buf, BUFFER_SIZE); if (n <= 0) return; /* EOF */ Write(s_server, buf, n); } } void* str_echo_2_client(void *arg) { size_t n; int s_client = ((pm_socket)arg)->s_client; int s_server = ((pm_socket)arg)->s_server; while (1) { n = Read(s_server, buffer_c, BUFFER_SIZE); if (n <= 0) return; /* EOF */ Write(s_client, buffer_c, n); } } void str_echo_via_repeater(int s_client) { int s_server, ret; struct sockaddr_in servaddr; s_server = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(port[portCurrent]); Inet_pton(AF_INET, serIp, &servaddr.sin_addr); Connect(s_server, (struct sockaddr *) &servaddr, sizeof(servaddr)); pthread_t tid; m_socket socket; socket.s_client = s_client; socket.s_server = s_server; Pthread_create(&tid, NULL, str_echo_2_client, (void *) &socket); str_send_2_server(s_server, s_client, buffer_s); Shutdown(s_server, 2); Shutdown(s_client, 2); Close(s_server); Close(s_client);} void sig_chld(int signo) { pid_t pid; int stat; while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0) printf("child %d terminated\n", pid); return;} int main(int argc, char *argv[]) { int listenfd, connfd; size_t clilen; struct sockaddr_in cliaddr, servaddr; int i; if (argc < 3 || argc > MAX_SERVER + 2) { printf("usage: repeater IP port1 [port2 port3 ... port10]\n"); return 1; } serIp = argv[1]; serAmount = argc - 2; for (i=0; i<serAmount; i++) port[i] = atoi(argv[i+2]); portCurrent = 0; signal(SIGCHLD, sig_chld); listenfd = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl (INADDR_ANY); servaddr.sin_port = htons(SERVPORT); Bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); Listen(listenfd, BACKLOG); while (1) { clilen = sizeof(cliaddr); connfd = Accept(listenfd, (struct sockaddr *) &cliaddr, &clilen); if (connfd < 0 && connfd == EINTR) continue; if (Fork() == 0) { Close(listenfd); str_echo_via_repeater(connfd); return 0; } // 实现负载均衡算法 portCurrent = (++portCurrent % serAmount); Close(connfd); } return 0;}
2. 服务器
// ser.c#include "unp.h" #define BUFFER_SIZE BUFFSIZE//#define SERVPORT 9993#define BACKLOG 20 char buffer[BUFFER_SIZE]; void str_echo2(int sockfd, char* buf) { ssize_t n; while (1) { n = Read(sockfd, buf, BUFFER_SIZE); if (n > 0) Write(sockfd, buf, n); else return; }} void sig_chld(int signo) { pid_t pid; int stat; while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0) printf("child %d terminated\n", pid); return;} int main(int argc, char *argv[]) { int listenfd, connfd; size_t clilen; struct sockaddr_in cliaddr, servaddr; int SERVPORT; if (argc != 2) { printf("usage: ser PORT\n"); return 1; } SERVPORT = atoi(argv[1]); signal(SIGCHLD, sig_chld); listenfd = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl (INADDR_ANY); servaddr.sin_port = htons(SERVPORT); Bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); Listen(listenfd, BACKLOG); while (1) { clilen = sizeof(cliaddr); connfd = Accept(listenfd, (struct sockaddr *) &cliaddr, &clilen); if (connfd < 0 && connfd == EINTR) continue; if (Fork() ==0) { Close(listenfd); str_echo2(connfd, buffer); Close(connfd); return 0; } Close(connfd); } return 0;}
3. 客户端
// cln.c#include "unp.h" #define BUFFER_SIZE BUFFSIZE#define SERVPORT 9000#define BACKLOG 20 char sbuffer[BUFFER_SIZE];char rbuffer[BUFFER_SIZE]; void str_cli1(int infd, int outfd, int sockfd) { size_t n; while (1) { n = Read(infd, sbuffer, BUFFER_SIZE); if (n <= 0) return; /* EOF */ Write(sockfd, sbuffer, n); n = Read(sockfd, rbuffer, BUFFER_SIZE); if (n <= 0) return; /* FIN */ Write(outfd, rbuffer, n); } } int main(int argc, char *argv[]) { int sockfd, ret; struct sockaddr_in servaddr; if (argc != 2) { printf("usage: cln IP\n"); return 1; } sockfd = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(SERVPORT); Inet_pton(AF_INET, argv[1], &servaddr.sin_addr); Connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); str_cli1(fileno(stdin), fileno(stdout), sockfd); /* do it all */ Close(sockfd); return 0;}
0 0
- Linux下实现简单Echo中继服务器
- epoll实现简单echo服务器
- linux echo 服务器模型
- linux-echo服务器
- linux-echo服务器
- Windows平台基于多进程的echo服务器简单实现
- 简单的echo服务器与客户端的实现
- [UNIX网络编程] sun rpc实现的简单echo服务器
- socket实现简单的echo应答服务器和客户端
- linux socke编程实例:一个简单的echo服务器程序
- linux socke编程实例:一个简单的echo服务器程序
- linux socke编程实例:一个简单的echo服务器程序
- linux echo简单总结
- 简单的echo服务器程序
- linux下echo详解
- linux下echo命令
- linux网络编程(实现简单的echo服务)
- Linux网络编程echo简单示例2--select实现
- uva11732 字典树
- MATLAB 无约束一维极值问题
- 【CSAPP】proxy Lab代理实验
- 双向冒泡排序
- SQL语句执行效率及分析
- Linux下实现简单Echo中继服务器
- unity3d中的local和global
- 排序分类基本介绍
- 树与二叉树
- 设计模式—单例模式(Singleton pattern)
- ST算法
- template.js插件--好用的模板插件
- 1795 The least one【素数打表】
- [odroid-pc] ubuntu12.o4编译烧写android4.0 forodroidpc