Linux socket 服务器

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

using namespace std;

#define DEFAULT_PORT 8000
#define MAXLINE 4096

struct Packet    
{    
    unsigned int      msgLen;     //数据部分的长度(注:这是网络字节序)    
    char            text[1024]; //报文的数据部分    
};  


/**实现:  
这两个函数只是按需多次调用read和write系统调用直至读/写了count个数据  
**/    
/**返回值说明:  
    == count: 说明正确返回, 已经真正读取了count个字节  
    == -1   : 读取出错返回  
    <  count: 读取到了末尾  
**/    
ssize_t readn(int fd, void *buf, size_t count)    
{    
    size_t nLeft = count;    
    ssize_t nRead = 0;    
    char *pBuf = (char *)buf;    
    while (nLeft > 0)    
    {    
        if ((nRead = read(fd, pBuf, nLeft)) < 0)    
        {    
            //如果读取操作是被信号打断了, 则说明还可以继续读    
            if (errno == EINTR)    
                continue;    
            //否则就是其他错误    
            else    
                return -1;    
        }    
        //读取到末尾    
        else if (nRead == 0)    
            return count-nLeft;    
    
        //正常读取    
        nLeft -= nRead;    
        pBuf += nRead;    
    }    
    return count;    
}    

/**返回值说明:  
    == count: 说明正确返回, 已经真正写入了count个字节  
    == -1   : 写入出错返回  
**/    
ssize_t writen(int fd, const void *buf, size_t count)    
{    
    size_t nLeft = count;    
    ssize_t nWritten = 0;    
    char *pBuf = (char *)buf;    
    while (nLeft > 0)    
    {    
        if ((nWritten = write(fd, pBuf, nLeft)) < 0)    
        {    
            //如果写入操作是被信号打断了, 则说明还可以继续写入    
            if (errno == EINTR)    
                continue;    
            //否则就是其他错误    
            else    
                return -1;    
        }    
        //如果 ==0则说明是什么也没写入, 可以继续写    
        else if (nWritten == 0)    
            continue;    
    
        //正常写入    
        nLeft -= nWritten;    
        pBuf += nWritten;    
    }    
    return count;    
}    


bool sendMessage(int clientfd,Packet buf){
    unsigned int lenHost = strlen(buf.text);  
    buf.msgLen = htonl(lenHost);  
    if (writen(clientfd, &buf, sizeof(buf.msgLen)+lenHost) == -1)    
        return false;
    return true;
}

void hander(int clientfd,struct Packet buf){
    cout<<"开始处理"<<endl;
    //cout<<buf.msgLen<<buf.text;
    // string cmd = string(buf.text);
    cout<<strlen(buf.text)<<"  "<<buf.text<<endl;
    if(buf.text == "结束"){
        close(clientfd);
        cout<<"结束进程"<<endl;
        exit(0);
    }
    cout<<"处理结束"<<endl;
    sendMessage(clientfd,buf);

}

void echo(int clientfd)    
{    
    struct Packet buf;    
    int readBytes;    
    memset(&buf,0,sizeof(buf));
    //首先读取首部    
    while ((readBytes = readn(clientfd, &buf.msgLen, sizeof(buf.msgLen))) > 0)    
    {    
        //网络字节序 -> 主机字节序    
        int lenHost = ntohl(buf.msgLen);    
        //然后读取数据部分    
        readBytes = readn(clientfd, buf.text, lenHost);    
        if (readBytes == -1){
            cerr << "readn socket error..." << endl;    
            exit(1);//err_exit("readn socket error");    
        }else if (readBytes != lenHost)    
        {    
            cerr << "client connect closed..." << endl;    
            return ;    
        }    
        //cout <<lenHost <<"  "<<buf.text<<endl;    
        hander(clientfd,buf);
        memset(&buf,0,sizeof(buf));
    }    
    if (readBytes == -1)    //err_exit("read socket error");    
        cerr << "read socket error" << endl;
    else if (readBytes != sizeof(buf.msgLen))    
        cerr << "client connect closed..." << endl;
            
}    

int Init(int port){
    int    socket_fd, connect_fd;
    struct sockaddr_in     servaddr;
    char    buff[4096];
    int     n;
    //初始化Socket
    if( (socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
    printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }
    //初始化
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址。
    servaddr.sin_port = htons(port);//设置的端口为DEFAULT_PORT
 
    //将本地地址绑定到所创建的套接字上
    if( bind(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
    printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }
    //开始监听是否有客户端连接
    if( listen(socket_fd, 10) == -1){
    printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }
    return socket_fd;
}

int accept(int socket_fd){
    int connect_fd;
         printf("======waiting for client's request======\n");
    //阻塞直到有客户端连接,不然多浪费CPU资源。
        if( (connect_fd = accept(socket_fd, (struct sockaddr*)NULL, NULL)) == -1){
        printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
        }
        return connect_fd;
}

int main(int argc, char** argv)
{

    int sockfd = Init(8000);

    int connect_fd = accept(sockfd); // 阻塞
    if(!fork()){
    cout<<"开始echo"<<endl;
    echo(connect_fd);
    }
    close(connect_fd);
    close(sockfd);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值