socket编程

本文详细介绍了TCP/IP编程中的socket操作,包括创建socket、bind功能、sockaddr_in结构以及在多进程中实现TCP服务器的过程,涉及listen、accept和信号处理等内容。
摘要由CSDN通过智能技术生成

前言知识 

sock udp编程

socket

用来创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)

int socket(int domain, int type, int protocol)

第一个参数代表了作用域,常用的一般就这三个

第二个参数是类型,用什么样的方式发送,选择udp或者tcp

第三个参数在这我们可以先忽略填0就ok 

bind

bind的作用就是本地主机与套接字绑定

 sockaddr_in结构体

里面包含了端口号port,本地地址addr还有common

local.sin_family=AF_INET

在该结构体中,family就代表协议家族的,这里默认和socket中第一个参数‘域’保持一致

local.sin_port=htons(_port)

port可以直接使用htons函数去转换

这些函数名很好记,h表示host,n表示network,l表示32位长整数,s表示16位短整数。 例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回 ; 如果主机是大端字节序,这些 函数不做转换,将参数原封不动地返回。

local.sin_addr.s_addr=inet_addr(_ip.c_str())

inet_addr函数可以直接将点分十进制ip转换成四个字节的数据存入local中

bind(_sock,(struct sockaddr*)&local,sizeof local)

recvfrom

从网络中接受数据消息,第一个参数是sockfd,sockfd相当于文件描述符,buff是缓冲区,flags是是否阻塞,这里默认填0,代表阻塞,src_addr是要将从网络中来的数据的套接字取到,addrelen是输入输出型参数,输入peer缓冲区大小,输出实际读取到的peer,成功读取到返回字节数量,不成功返回

sendto

回写给客户端数据

第一个参数还是文件描述符,第二个是缓冲区,第三个阻塞等待0,第四个客服端的套接字地址,第五个为输入输出型参数socklen_t

运行服务器成功

socket tcp编程

tcp是面向有连接的编程,需要连接上才能使用

多进程版tcp服务器

初始化服务器和udp一样,先创建套接字,和udp不同的是这里用的是SOCK_STREAM,代表了流式,而udp采用的是数据报的形式,然后因为是服务端,所以正常来说是绑定主机号的,绑定后后,使用listen去监听

void initserver(){
        _listensock=socket(AF_INET,SOCK_STREAM,0);
        if(_listensock<0){
            logMessage(FATAL,"create sock error%d:%s",errno,strerror(errno));
            exit(2);
        }
        logMessage(NORMAL,"create sock success:%d",_listensock);
        struct sockaddr_in local;
        memset(&local,0,sizeof local);
        local.sin_family=AF_INET;
        local.sin_port=htons(_port);
        local.sin_addr.s_addr=_ip.empty()?INADDR_ANY:inet_addr(_ip.c_str());
        if(bind(_listensock,(struct sockaddr*)&local,sizeof local)<0){
             logMessage(FATAL,"bind error%d:%s",errno,strerror(errno));
             exit(3);
        }
         logMessage(NORMAL,"bind local success:%d",_listensock);

         if(listen(_listensock ,gbacklog)<0){
            logMessage(FATAL,"listen error%d:%s",errno,strerror(errno));
            exit(4);
         }
         logMessage(NORMAL,"init success") ;
    }

这里在最开头做一个信号处理当子进程退出的时候直接忽略,那么就不会产生僵尸进程了,先创建数据结构sockaddr_in主要是存储ip和prot用的,这里是接收客户端的sock,拿到后创建子进程,处理接受数据。

 void start(){ 
        signal(SIGCHLD,SIG_IGN);
        while(true){
            struct sockaddr_in src;
            socklen_t len=sizeof(src);
            int sevicesock=accept(_listensock,(struct sockaddr*)&src,&len);
            if(sevicesock<0){
                 logMessage(FATAL,"sevicesock create error%d:%s",errno,strerror(errno));
                     continue;
            }
            uint16_t clientport=ntohs(src.sin_port);
            std::string clientip=inet_ntoa(src.sin_addr);
                 logMessage(NORMAL,"create sevicesock success%d %s %d",sevicesock,clientip.c_str(),clientport) ;
                
                pid_t id=fork();
                if(id==0){
                    close(_listensock);
                    sevice(sevicesock,clientip,clientport);
                    exit(0);
                }
                close(sevicesock);
            
                    }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值