建阳网站建设,描述网站的含义,今天出入上海最新通知,现在做网站建设都是自建【Linux网络编程三】Udp套接字编程(简易版服务器#xff09; 一.创建套接字二.绑定网络信息1.构建通信类型2.填充网络信息①网络字节序的port②string类型的ip地址 3.最终绑定 三.读收消息1.服务器端接收消息recvfrom2.服务器端发送消息sendto3.客户端端发送消息sendto4.客户端… 【Linux网络编程三】Udp套接字编程(简易版服务器 一.创建套接字二.绑定网络信息1.构建通信类型2.填充网络信息①网络字节序的port②string类型的ip地址 3.最终绑定 三.读收消息1.服务器端接收消息recvfrom2.服务器端发送消息sendto3.客户端端发送消息sendto4.客户端端接收消息recvfrom 四.关于绑定ip与port细节五.客户端不需要主动绑定六.客户端/服务器端代码 UDP套接字编程 网络通信本质是进程之间通信所以我们需要两个进程来网络通信假设一个为服务器进程一个为客户端进程演示。 一.创建套接字 socket()接口可以用来创建套接字它总共有三个参数。 第一个参数domain表示通信的类型是使用网络通信还是本地通信由用户选择当传入AF_INET/AF_INET6时表示使用网络通信。 第二个参数type表示套接字的类型是TCP呢还是UDP呢。如果传递SOCK_DGRAM表示是UDP如果传递的SOCK_STREAM表示是TCP. 第三个参数protocol表示协议默认为0. 创建套接字成功后会返回一个文件描述符sockfd也就是创建套接字的本质就是打开一个文件
服务器端进程在创建完套接字后该做什么呢该套接字(文件)是属于你服务器进程的然后呢假设客户端也打开一个套接字(文件)这两个套接字文件都是属于同一个也就是满足了进程间通信的前提条件能看到一个共享资源。 而两个进程看到同一份资源后那么该如何准确的发送给对方呢因为可能打开这个套接字文件的进程有很多。所以接下来就是两个进程需要知道各自对方能够唯一标识自己的ip地址和端口号等网络信息。这样才能够准确的将数据从客户端进程发送给服务器进程。 // 1.创建udp套接字本质就是打开网络套接字文件_sockfd socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd 0) // 表示创建失败{lg(Fatal, socket create error,socket: %d, _sockfd);exit(SOCKET_ERR); // 创建失败之间退出}二.绑定网络信息
套接字创建成功后就相当于打开了一个文件该文件是就两个进程通信的共享资源不过要想准确通信还需要知道各自进程的ip地址和端口号这样往文件里传输数据时对端才能准确接收到也就是这个文件需要绑定一些各自进程的网络信息才能准确的传递到对端。 进程之间网络通信需要先绑定端口号这里创建完套接字后就需要让该进程的端口号与套接字绑定。这样对端的进程才能找到这个进程 第一个参数就是创建的套接字也就是文件对象 第二个参数就是要绑定的该进程的网络信息包括端口号ip地址等 第三个参数是网络信息结构体对象的大小 这个网络信息结构体对象要求传的是统一的接口但是你实际使用什么类型的网络通信你就定义什么类型然后传递时强转即可。 // 在绑定套接信息之前需要先将对应的结构体对象填充完毕sock_addrstruct sockaddr_in local; // 网络通信类型bzero(local, sizeof(local)); // 将内容置为0local.sin_family AF_INET; // 网络通信类型local.sin_port htons(_port); // 网络通信中端口号需要不断发送所以需要符合网络字节序,主机---网络字节序local.sin_addr.s_addr inet_addr(_ip.c_str()); // 需要将string类型的ip转换成int类型并且还需要满足网络字节序的要求socklen_t len sizeof(local);// 以上只是将要绑定的信息填充完毕套接字(网络文件)而还没有绑定套接信息1.构建通信类型
比如如果我要网络通信那么就需要定义一个sockaddr_in结构体对象。 该结构体对象里有三个需要初始化的参数 1.sin_family:要使用的通信类型 2.sin_port:该进程的端口号 3.sin_addr:该进程的ip地址 sin_addr这个结构体对象里面只有一个参数s_addr这个也就是真正的ip地址。 2.填充网络信息
①网络字节序的port
在给套接字绑定网络信息之前需要将网络信息给构建好就比如端口号我们需要将当前进程的端口号填充到sockaddr_in这个结构体对象里。 不过端口号在网络通信中是要不但的来回发送的不管是客户端还是服务器端两个进程通信就必须知道对方的端口号。 所以端口号是需要发送到网络里的所以在填充时必须是网络字节序。 也就是主机转网络字节序
②string类型的ip地址
用户一般喜欢用string类型的ip地址类型这样比较好显示。 但是系统里的ip是uint16_t类型的所以我们在填充初始化时. 【要求1】首先需要将string类型的参数转换成uint16_t类型。
【要求2】其次ip地址也需要发送到网络里的所以也必须是网络字节序。 系统里给了我们相关的接口inet_addr(char*cp)
它就是可以将string类型的数据转换成uint16_t类型并且将主机字节序转换成网络字节序。
3.最终绑定 if (bind(_sockfd, (const struct sockaddr *)local, len) 0) // 绑定失败{lg(Fatal, bind sockfd error,errno%d,err string:%s, errno, strerror(errno));exit(BIND_ERR);}lg(Info, bind sockfd success,errno%d,err string:%s, errno, strerror(errno)); // 绑定成功三.读收消息
1.服务器端接收消息recvfrom
一般客户端进程对服务器进程发送消息服务器进程接收客户端发送的消息。那么服务器进程如何接收客户端发送的消息呢 服务器进程是从套接字接收消息也就是该进程创建的文件里接收。 不过服务器除了能够接收到消息还需要知道是谁给它发送的消息这样它才可以将消息再发送回去。 所以就需要一个sockaddr_in结构体对象作为输出型参数将发送端的网络信息存储下来。也就是将客户端的网络信息带出来。 所以recvfrom的功能 1.除了接收到对端发送的消息内容 2.还可以知道对端的网络消息。知道是谁发送过来的。 struct sockaddr_in client;socklen_t len sizeof(client);// 服务器接收到消息它还需要知道谁给它发送的为了后续将应答返回过去// 利用一个输出型参数将对方的网络信息填充到里面ssize_t n recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)client, len);if (n 0){lg(Warning, recvfrom sockfd err,errno: %d, err string %s, errno, strerror(errno));continue;}// 读取成功将网络文件里的消息读取到buffer里buffer[n] 0; // 字符串形式2.服务器端发送消息sendto
服务器一般只要用来接收其他客户端的消息然后加工处理再将数据发送回去所以服务器将数据再发送回客户端也就是往套接字里发送消息而要发送的客户端网络信息刚好被存储在输出型参数里。因为客户但是主动发送消息的服务器一定是先收到客户端发送的消息然后会将客户端的网络消息存储起来再根据客户端网络信息发送回去。 // 3.将应答发送回去
// 发送给谁呢服务器知道吗服务器知道因为在接收消息时服务器就用一个输出型参数将客户端的网络消息保存下来了
sendto(_sockfd, echo_string.c_str(), echo_string.size(), 0, (const struct sockaddr *)client, len);因为服务器端在接收客户端发送的消息时还会保存客户端的网络信息所以如果服务器想发送消息给客户端是很容易的。 3.客户端端发送消息sendto
客户端将消息发送给服务器端该怎么发送呢通过套接字(文件)发送给服务器发送时需要服务器端的网络信息比如ip地址端口号等这样客户端才能准确的发送给该服务器端。
//构建服务器端的网络信息std::string serverip argv[1];uint16_t serverport std::stoi(argv[2]);struct sockaddr_in server;bzero(server, sizeof(server));server.sin_family AF_INET;server.sin_addr.s_addr inet_addr(serverip.c_str()); // 将string类型转换成int类型并且是网络字节序server.sin_port htons(serverport);socklen_t len sizeof(server);// 1.创建套接字---本质就是打开网络文件int sockfd socket(AF_INET, SOCK_DGRAM, 0);if (sockfd 0){cout socket create err endl;return 1;}// 创建成功// 2.需要绑定吗系统会给我自动绑定首次发送的时候就会绑定char outbuffer[1024];string message;getline(cin, message);//1.发送给服务器sendto(sockfd, message.c_str(), message.size(), 0, (const struct sockaddr *)server, len);4.客户端端接收消息recvfrom
客户端要想接收服务器发送回来的消息只需要读取套接字里的消息即可。利用recvfrom接口读取客户端的套接字。 不过还需要定义一个结构体对象用来保存服务器端的网络信息虽然客户端已经知道但是接口要求所以必须定义。 struct sockaddr_in temp;socklen_t lsizeof(temp); //2.接收服务器的应答ssize_t srecvfrom(sockfd,outbuffer,1023,0,(struct sockaddr*)temp,l);四.关于绑定ip与port细节
【细节1】当服务器端绑定ip时如果ip地址是’0.0.0.0则表示任意ip地址绑定。 就表示不管客户端发送时目的ip是多少只要消息发送到服务器的主机上那么都可以接收并将端口号往上发送。
也就是只要是发送到我这台主机上的报文那么就会忽略到该报文的目的ip地址是多少只看端口号。 这就表示任意ip地址绑定。相当于一种动态绑定。可以接收到所有发送到我这台主机上的报文。并往上传递。 还要注意在云服务器上公用ip是不能随意绑定的无法直接绑定不管是TCP还是UDP。除非是127.0.0.1这个ip地址是专门用来检测服务器和客户端的。其他的不要瞎绑定。但是在虚拟机上可以。 【细节2】端口号不是随意绑定的有些是已经被固定使用的【01023】是属于系统内定的端口号一般要有固定的应用层协议使用。 所以我们最好使用1023后面的。
【总结】 如果服务器端的ip地址默认是0的话那么我们只需要知道服务器端的端口号即可。
五.客户端不需要主动绑定 所以客户端是不需要显示的绑定相关的端口号和ip地址的。操作系统会帮它自动绑定。 本质原因是用户不关心客户端的端口号和ip地址等网络信息所以不需要显示绑定。 关键是要唯一。由操作系统随机选择。
但是服务器端必须主动绑定端口号为什么呢 因为用户关心服务器的端口号必须知道服务器端的端口号。不然无法找到服务器端。
六.客户端/服务器端代码
【客户端】
#include iostream
#include cstdlib
#include unistd.h
#include strings.h
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.husing namespace std;#include iostream
#include strings.h
#include sys/types.h
#include cstring
#include unistd.h
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.h
using namespace std;
// 客户端
void Usage(std::string proc)
{std::cout \n\r./Usage: proc serverip serverport\n endl;
}
// 启动客户端时要求是 ./Client 服务器ip 服务器port
int main(int argc, char *argv[])
{if (argc ! 3){Usage(argv[0]);exit(0);}std::string serverip argv[1];uint16_t serverport std::stoi(argv[2]);struct sockaddr_in server;bzero(server, sizeof(server));server.sin_family AF_INET;server.sin_addr.s_addr inet_addr(serverip.c_str()); // 将string类型转换成int类型并且是网络字节序server.sin_port htons(serverport);socklen_t len sizeof(server);// 1.创建套接字---本质就是打开网络文件int sockfd socket(AF_INET, SOCK_DGRAM, 0);if (sockfd 0){cout socket create err endl;return 1;}// 创建成功// 2.需要绑定吗系统会给我自动绑定首次发送的时候就会绑定// 3.往服务器的套接字里发送消息--需要知道服务器的ip和端口号,目的ip和目的port,将ip和port填入结构体对象里char outbuffer[1024];string message;while (true){coutPlease enter ;getline(cin, message);//1.发送给服务器sendto(sockfd, message.c_str(), message.size(), 0, (const struct sockaddr *)server, len);struct sockaddr_in temp;socklen_t lsizeof(temp); //2.接收服务器的应答ssize_t srecvfrom(sockfd,outbuffer,1023,0,(struct sockaddr*)temp,l);if(s0){//接收成功outbuffer[s]0;coutoutbufferendl;}}close(sockfd);return 0;
}【服务器端】 -0,0 1,103
#pragma once#include Log.hpp
#include iostream
#include string
#include strings.h
#include cstring
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.h
#include functional
std::string defaultip 0.0.0.0;
uint16_t defaultport 8080;
Log lg; // 日志默认往显示屏打印
typedef std::functionstd::string(const std::string) func_t;//相当于定义了一个函数指针
//返回值是string类型函数参数也是string类型利用函数回调的方法将服务器端对数据的处理操作进行分离由上层传递的函数来决定如何处理
enum
{SOCKET_ERR 1,BIND_ERR
};
class Udpserver
{
public:Udpserver(const uint16_t port defaultport, std::string ip defaultip) : _sockfd(0), _port(port), _ip(ip){}void Init(){// 1.创建udp套接字本质就是打开网络套接字文件_sockfd socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd 0) // 表示创建失败{lg(Fatal, socket create error,socket: %d, _sockfd);exit(SOCKET_ERR); // 创建失败之间退出}// 创建成功lg(Info, socket create success,socket: %d, _sockfd);// 2.绑定服务器的套接信息比如ip和端口号// 在绑定套接信息之前需要先将对应的结构体对象填充完毕sock_addrstruct sockaddr_in local; // 网络通信类型bzero(local, sizeof(local)); // 将内容置为0local.sin_family AF_INET; // 网络通信类型local.sin_port htons(_port); // 网络通信中端口号需要不断发送所以需要符合网络字节序,主机---网络字节序local.sin_addr.s_addr inet_addr(_ip.c_str()); // 需要将string类型的ip转换成int类型并且还需要满足网络字节序的要求socklen_t len sizeof(local);// 以上只是将要绑定的信息填充完毕套接字(网络文件)而还没有绑定套接信息if (bind(_sockfd, (const struct sockaddr *)local, len) 0) // 绑定失败{lg(Fatal, bind sockfd error,errno%d,err string:%s, errno, strerror(errno));exit(BIND_ERR);}lg(Info, bind sockfd success,errno%d,err string:%s, errno, strerror(errno)); // 绑定成功}void Run(func_t func) // 服务器是一旦启动不会退出服务器接收消息并发送答应{// 1.接收信息char buffer[SIZE];while (true){struct sockaddr_in client;socklen_t len sizeof(client);// 服务器接收到消息它还需要知道谁给它发送的为了后续将应答返回过去// 利用一个输出型参数将对方的网络信息填充到里面ssize_t n recvfrom(_sockfd, buffer, sizeof(buffer)-1, 0, (struct sockaddr *)client, len);if (n 0){lg(Warning, recvfrom sockfd err,errno: %d, err string %s, errno, strerror(errno));continue;}// 读取成功将网络文件里的消息读取到buffer里buffer[n] 0; // 字符串形式// 2.加工处理// std::string info buffer;// std::string echo_string server echo# info;std::string infobuffer;std::string echo_stringfunc(info);//将接收的信息由外层函数进行处理// 3.将应答发送回去// 发送给谁呢服务器知道吗服务器知道因为在接收消息时服务器就用一个输出型参数将客户端的网络消息保存下来了sendto(_sockfd, echo_string.c_str(), echo_string.size(), 0, (const struct sockaddr *)client, len);}}~Udpserver(){if (_sockfd 0)close(_sockfd);}private:int _sockfd; // 套接字文件描述符std::string _ip; // 我们习惯用string类型的ip地址uint16_t _port; // 服务器进程的端口号
}; #include Udpserver.hpp
#include memory
#include cstdio
#include stdlib.h
// 120.78.126.148 点分十进制字符串风格的IP地址
std::string handler(const std::string info)
{ std::string resget a message: ;resinfo;std::coutresstd::endl;return res;//最后将处理的数据返回回去
}#include Udpserver.hpp
#include memory
#include cstdiovoid Usage(std::string proc)
{std::cout\n\rUsage: proc port[1024]\nstd::endl;
}
//服务器进程启动时按照./Udpserverport的形式传递
int main(int args,char* argv[])
{if(args!2){Usage(argv[0]);exit(0);}uint16_t portstd::stoi(argv[1]);std::unique_ptrUdpserver svr(new Udpserver(port));//首先创建一个服务器对象指针//智能指针用一个UdpServer指针来管理类对象svr-Init();//初始化服务器svr-Run(handler);//启动服务器return 0;
} 文章转载自: http://www.morning.pctsq.cn.gov.cn.pctsq.cn http://www.morning.qzsmz.cn.gov.cn.qzsmz.cn http://www.morning.kfldw.cn.gov.cn.kfldw.cn http://www.morning.dbqg.cn.gov.cn.dbqg.cn http://www.morning.rqjxc.cn.gov.cn.rqjxc.cn http://www.morning.sjsks.cn.gov.cn.sjsks.cn http://www.morning.bfcxf.cn.gov.cn.bfcxf.cn http://www.morning.ddzqx.cn.gov.cn.ddzqx.cn http://www.morning.kxltf.cn.gov.cn.kxltf.cn http://www.morning.xjqkh.cn.gov.cn.xjqkh.cn http://www.morning.gkjnz.cn.gov.cn.gkjnz.cn http://www.morning.ygrkg.cn.gov.cn.ygrkg.cn http://www.morning.nkqxb.cn.gov.cn.nkqxb.cn http://www.morning.llmhq.cn.gov.cn.llmhq.cn http://www.morning.dhqg.cn.gov.cn.dhqg.cn http://www.morning.fywqr.cn.gov.cn.fywqr.cn http://www.morning.nuobeiergw.cn.gov.cn.nuobeiergw.cn http://www.morning.czqqy.cn.gov.cn.czqqy.cn http://www.morning.zrjzc.cn.gov.cn.zrjzc.cn http://www.morning.pdghl.cn.gov.cn.pdghl.cn http://www.morning.flpjy.cn.gov.cn.flpjy.cn http://www.morning.hnhsym.cn.gov.cn.hnhsym.cn http://www.morning.ogzjf.cn.gov.cn.ogzjf.cn http://www.morning.tlbdy.cn.gov.cn.tlbdy.cn http://www.morning.xgxbr.cn.gov.cn.xgxbr.cn http://www.morning.xjpnq.cn.gov.cn.xjpnq.cn http://www.morning.jrslj.cn.gov.cn.jrslj.cn http://www.morning.mqlsf.cn.gov.cn.mqlsf.cn http://www.morning.ptlwt.cn.gov.cn.ptlwt.cn http://www.morning.xfmzk.cn.gov.cn.xfmzk.cn http://www.morning.pfbx.cn.gov.cn.pfbx.cn http://www.morning.rgksz.cn.gov.cn.rgksz.cn http://www.morning.wrlqr.cn.gov.cn.wrlqr.cn http://www.morning.yrctp.cn.gov.cn.yrctp.cn http://www.morning.prprj.cn.gov.cn.prprj.cn http://www.morning.rszwc.cn.gov.cn.rszwc.cn http://www.morning.qwrb.cn.gov.cn.qwrb.cn http://www.morning.mlyq.cn.gov.cn.mlyq.cn http://www.morning.dbcw.cn.gov.cn.dbcw.cn http://www.morning.ylpwc.cn.gov.cn.ylpwc.cn http://www.morning.rxkl.cn.gov.cn.rxkl.cn http://www.morning.nnwpz.cn.gov.cn.nnwpz.cn http://www.morning.bnlch.cn.gov.cn.bnlch.cn http://www.morning.rdxnt.cn.gov.cn.rdxnt.cn http://www.morning.kybjr.cn.gov.cn.kybjr.cn http://www.morning.qfwzm.cn.gov.cn.qfwzm.cn http://www.morning.cfnsn.cn.gov.cn.cfnsn.cn http://www.morning.rjbb.cn.gov.cn.rjbb.cn http://www.morning.tkhyk.cn.gov.cn.tkhyk.cn http://www.morning.rrhfy.cn.gov.cn.rrhfy.cn http://www.morning.qbzdj.cn.gov.cn.qbzdj.cn http://www.morning.pmdlk.cn.gov.cn.pmdlk.cn http://www.morning.dnhdp.cn.gov.cn.dnhdp.cn http://www.morning.btqqh.cn.gov.cn.btqqh.cn http://www.morning.fqyxb.cn.gov.cn.fqyxb.cn http://www.morning.mkczm.cn.gov.cn.mkczm.cn http://www.morning.kbfzp.cn.gov.cn.kbfzp.cn http://www.morning.gwyml.cn.gov.cn.gwyml.cn http://www.morning.dtpqw.cn.gov.cn.dtpqw.cn http://www.morning.gjssk.cn.gov.cn.gjssk.cn http://www.morning.nqmdc.cn.gov.cn.nqmdc.cn http://www.morning.ynbyk.cn.gov.cn.ynbyk.cn http://www.morning.cjcry.cn.gov.cn.cjcry.cn http://www.morning.zfqdt.cn.gov.cn.zfqdt.cn http://www.morning.zfhwm.cn.gov.cn.zfhwm.cn http://www.morning.jfjbl.cn.gov.cn.jfjbl.cn http://www.morning.jpkk.cn.gov.cn.jpkk.cn http://www.morning.tnrdz.cn.gov.cn.tnrdz.cn http://www.morning.kzdwt.cn.gov.cn.kzdwt.cn http://www.morning.fwkq.cn.gov.cn.fwkq.cn http://www.morning.gtbjc.cn.gov.cn.gtbjc.cn http://www.morning.rtqyy.cn.gov.cn.rtqyy.cn http://www.morning.qxycf.cn.gov.cn.qxycf.cn http://www.morning.dblgm.cn.gov.cn.dblgm.cn http://www.morning.xmttd.cn.gov.cn.xmttd.cn http://www.morning.cfcdr.cn.gov.cn.cfcdr.cn http://www.morning.nzqqd.cn.gov.cn.nzqqd.cn http://www.morning.ldzss.cn.gov.cn.ldzss.cn http://www.morning.fqlxg.cn.gov.cn.fqlxg.cn http://www.morning.pxjp.cn.gov.cn.pxjp.cn