ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

linux网络编程-多client多server一个watcher

2021-12-03 23:59:51  阅读:171  来源: 互联网

标签:addr int watcher client linux sockfd server port


client.cpp-->client

server.cpp-->server

watcher.cpp+server.h-->watcher

client.cpp

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>

//从watcher获取可用的服务端
int connect_watcher(std::string& ip,unsigned short int& port)
{
    int sockfd;
    sockaddr_in watcher_addr;
    
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1)
    {
        printf("客户端创建sockfd失败\n");
        return -1;
    }
    memset(&watcher_addr,0,sizeof(sockaddr_in));
    watcher_addr.sin_family=AF_INET;
    watcher_addr.sin_port=htons(11112);
    watcher_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    //connect
    if(connect(sockfd,(sockaddr*)(&watcher_addr),sizeof(sockaddr))==-1)
    {
        printf("failed to connect to server\n");
        return -1;
    }
    char buffer[1024];
    int nbytes=read(sockfd,buffer,1023);
    if(nbytes>0)
    {
        printf("接收到watcher端%d个字节:\n",nbytes);
        buffer[nbytes]='\0';
        printf("%s\n",buffer);
        std::string server_info(buffer);
        //解析ip和port
        int pos=server_info.find(":");
        std::string ipstr=server_info.substr(0,pos);
        std::string portstr=server_info.substr(pos+1,server_info.size()-pos);
        if(ipstr.empty()||portstr.empty())
        {
            printf("failed to accquire server ip and port\n");
            return -1;
        }
        else
        {
            ip=ipstr;
            port=std::stoi(portstr);
            return 0;
        }

    }
    return -1;    
}

int main()
{
    //连接到watcher
    std::string server_ip;
    unsigned short int server_port;
    if(connect_watcher(server_ip,server_port)<0)
    {
        printf("failed to contact to wather...\n");
        return -1;
    }

    int sockfd;
    sockaddr_in server_addr;
    
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1)
    {
        printf("客户端创建sockfd失败\n");
        return -1;
    }
    memset(&server_addr,0,sizeof(sockaddr_in));
    server_addr.sin_family=AF_INET;
    server_addr.sin_port=htons(server_port);
    server_addr.sin_addr.s_addr = inet_addr(server_ip.c_str());

    //connect
    if(connect(sockfd,(sockaddr*)(&server_addr),sizeof(sockaddr))==-1)
    {
        printf("failed to connect to server\n");
        return -1;
    }

    char buffer[1024];
    while(true)
    {
        int nbytes=read(sockfd,buffer,1023);
        if(nbytes>0)
        {
            printf("接收到服务端%d个字节:\n",nbytes);
            buffer[nbytes]='\0';
            printf("%s\n",buffer);
        }
    }

    //close
    close(sockfd);
    return 0;
}

server.cpp

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>

int connect_watcher(unsigned short int port)
{
    int sockfd;
    sockaddr_in watcher_addr;
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1)
    {
        printf("服务端创建sockfd失败\n");
        return -1;
    }
    memset(&watcher_addr,0,sizeof(sockaddr_in));
    watcher_addr.sin_family=AF_INET;
    watcher_addr.sin_port=htons(11111);
    watcher_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    //connect to watcher
    if(connect(sockfd,(sockaddr*)(&watcher_addr),sizeof(sockaddr))==-1)
    {
        printf("failed to connect to watcher\n");
        return -1;
    }
    //把自己正在监听的端口发送给watcher端
    std::string msg="port="+std::to_string(port);
    int nbytes=msg.size();
    printf("即将发送%d个字节\n",nbytes);
    int nw=write(sockfd,msg.c_str(),nbytes);
    if(nw!=nbytes)
    {
        printf("写入socket失败\n");
        return -1;
    }
    //从watcher端读取信息
    char buffer[1024];
    int nb=read(sockfd,buffer,1023);
    if(nb>0)
    {
        printf("接收到watcher端%d个字节:\n",nb);
        buffer[nb]='\0';
        printf("%s\n",buffer);
    }
    return 0;
}

int main(int argc,char* argv[])
{
    if(argc<2)
    {
        printf("no port set!\n");
        return -1;
    }
    unsigned short int port=std::stoi(std::string(argv[1]));
    if(connect_watcher(port)<0)
    {
        printf("failed to contact to watcher...\n");
        return -1;
    }

    //当与watcher成功建立联系后,才会成为server
    int sockfd;
    sockaddr_in server_addr;
    sockaddr_in client_addr;

    //创建socket
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1)
    {
        printf("server failed to create the socket\n");
        return -1;
    }
    memset(&server_addr,0,sizeof(sockaddr_in));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    server_addr.sin_port=htons(port);

    //bind
    if(bind(sockfd,(sockaddr*)(&server_addr),sizeof(sockaddr))==-1)
    {
        printf("server failed to bind the socket\n");
        fprintf(stderr,"Socket error:%s\n",strerror(errno));
        return -1;
    }
    //listen
    if(listen(sockfd,5)==-1)
    {
        printf("server failed to listen the socket\n");
        return -1;
    }

    int sockfd_accepted;
    socklen_t sin_size=sizeof(sockaddr_in);
    while(true)
    {
        sockfd_accepted=accept(sockfd,(sockaddr*)(&client_addr),&sin_size);
        if(sockfd_accepted==-1)
        {
            printf("server accept sockfd error\n");

        }
        else
        {
            printf("server get a client connection from %d\n",client_addr.sin_port);
            //其他的处理过程
            char buffer[1024]="xxxxxxxxx";
            int nbytes=strlen(buffer);
            printf("即将发送%d个字节\n",nbytes);
            int nw=write(sockfd_accepted,buffer,nbytes);
            if(nw!=nbytes)
            {
                printf("写入socket失败\n");
            }
        }
    }
    close(sockfd);

    //
    printf("server will be closed!\n");
    return 0;
}

watcher.cpp

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#include <string>
#include <vector>

#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <pthread.h>

#include "server.h"
//监视所有可用的开启的服务端,
std::vector<Server> Servers_on_line;
int get_server_info(std::string& ip,unsigned short int& port);
void* server_proc(void*);
void* client_proc(void*);

int main()
{
    //开启监听服务端的工作
    pthread_t t1;
    pthread_create(&t1,NULL,&server_proc,NULL);
    
    pthread_t t2;
    pthread_create(&t2,NULL,&client_proc,NULL);

    pthread_join(t1,NULL);
    pthread_join(t2,NULL);    
    
    //
    printf("say goodby...\n");
    return 0;
}
//用于处理client连接的线程
void* client_proc(void*)
{
    unsigned short int port=11112;
    int sockfd;
    sockaddr_in watcher_addr;
    sockaddr_in client_addr;

    //创建socket
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1)
    {
        printf("watcher failed to create the socket\n");
        return (void*)-1;
    }
    memset(&watcher_addr,0,sizeof(sockaddr_in));
    watcher_addr.sin_family=AF_INET;
    watcher_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    watcher_addr.sin_port=htons(port);

    //bind
    if(bind(sockfd,(sockaddr*)(&watcher_addr),sizeof(sockaddr))==-1)
    {
        printf("watcher failed to bind the socket\n");
        fprintf(stderr,"Socket error:%s\n",strerror(errno));
        return (void*)-1;
    }
    //listen
    if(listen(sockfd,5)==-1)
    {
        printf("watcher failed to listen the socket\n");
        return (void*)-1;
    }

    int sockfd_accepted;
    socklen_t sin_size=sizeof(sockaddr_in);
    while(true)
    {
        sockfd_accepted=accept(sockfd,(sockaddr*)(&client_addr),&sin_size);
        if(sockfd_accepted==-1)
        {
            printf("watcher accept sockfd error\n");
        }
        else
        {
            printf("watcher get a client connection from %d\n",client_addr.sin_port);
            //其他的处理过程
            std::string server_ip;
            unsigned short int server_port;
            get_server_info(server_ip,server_port);
                        
            //将获取到的服务器地址发送给客户端
            std::string msg=server_ip+":"+std::to_string(server_port);
            int nbytes=msg.size();
            printf("即将发送%d个字节\n",nbytes);
            int nw=write(sockfd_accepted,msg.c_str(),nbytes);
            if(nw!=nbytes)
            {
                printf("写入socket失败\n");
            }
        }
    }
    close(sockfd);

    //
    printf("watcher will be closed!\n");
    return 0;
}

//用于处理server连接和记录的线程
void* server_proc(void*)
{
    unsigned short int port=11111;
    int sockfd;
    sockaddr_in watcher_addr;
    sockaddr_in server_addr;

    //创建socket
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1)
    {
        printf("watcher failed to create the socket\n");
        return (void*)-1;
    }
    memset(&watcher_addr,0,sizeof(sockaddr_in));
    watcher_addr.sin_family=AF_INET;
    watcher_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    watcher_addr.sin_port=htons(port);

    //bind
    if(bind(sockfd,(sockaddr*)(&watcher_addr),sizeof(sockaddr))==-1)
    {
        printf("watcher failed to bind the socket\n");
        fprintf(stderr,"Socket error:%s\n",strerror(errno));
        return (void*)-1;
    }
    //listen
    if(listen(sockfd,5)==-1)
    {
        printf("watcher failed to listen the socket\n");
        return (void*)-1;
    }

    int sockfd_accepted;
    socklen_t sin_size=sizeof(sockaddr_in);
    while(true)
    {
        sockfd_accepted=accept(sockfd,(sockaddr*)(&server_addr),&sin_size);
        if(sockfd_accepted==-1)
        {
            printf("watcher accept sockfd error\n");
        }
        else
        {
            printf("watcher get a server connection from %d\n",server_addr.sin_port);
            //其他的处理过程
            std::string server_ip;
            unsigned short int server_port;

            //接收服务端发来的监听端口信息
            char buffer[1024];
            int nbytes=read(sockfd_accepted,buffer,1023);
            if(nbytes>0)
            {
                printf("接收到服务端%d个字节:\n",nbytes);
                buffer[nbytes]='\0';
                printf("%s\n",buffer);
                std::string server_listen_port(buffer);
                int pos=server_listen_port.find("=");
                std::string portstr=server_listen_port.substr(pos+1,server_listen_port.size()-pos);
                std::string msg="ok";
                if(portstr.empty())
                {
                    printf("server's listen port error\n");
                    msg="not ok...";
                }
                //发送给服务端
                
                int nbytes=msg.size();
                printf("即将发送%d个字节\n",nbytes);
                int nw=write(sockfd_accepted,msg.c_str(),nbytes);
                if(nw!=nbytes)
                {
                    printf("写入socket失败\n");
                }
                else
                {
                    Servers_on_line.push_back(Server(inet_ntoa(server_addr.sin_addr),std::stoi(portstr)));
                }
            }
            else
            {

            }            

        }
    }
    close(sockfd);

    printf("server will be closed!\n");
    return (void*)0;
}

int get_server_info(std::string& ip,unsigned short int& port)
{
    //获取一个可用的server的ip和port
    if(Servers_on_line.empty())
    {
        ip="";
        port=0;
        printf("now no server on line\n");
        return -1;
    }
    int id=rand()%Servers_on_line.size();
    ip=Servers_on_line[id].ip_;
    port=Servers_on_line[id].port_;
    return 0;
}

 server.h

#include <string>

class Server
{

public:
    Server(std::string ip,unsigned short int port);
    ~Server();
public:
    std::string ip_;
    unsigned short int port_;
};

Server::Server(std::string ip,unsigned short int port):ip_(ip),port_(port)
{
}

Server::~Server()
{
}

标签:addr,int,watcher,client,linux,sockfd,server,port
来源: https://blog.csdn.net/xiyangxiaoguo/article/details/121709339

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有