1、socket函数
函数原型:
#include <sys/socket.h> int socket(int domain, int type, int protocol);
参数解析:
作用:
socket函数的作用是创建一个套接字描述符(文件描述符),这个描述符是后续进行网络通信(绑定、监听、连接、收发数据)的唯一标识。
一、写一个回显程序:客户端发什么,服务器端就回什么
(1)、创建一个udp socket套接字:
cpp
#pragma once
#include<iostream>
using namespace std;
#include<sys/types.h>
#include<sys/socket.h>
#include<string>
#include<cstdlib>
class UdpServer
{
public:
UdpServer(){}
//初始化一个socket套接字
void InitServer()
{
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd < 0)
{
cout<<"创建失败"<<endl;
exit(1);
}
}
void start()
{
}
~UdpServer()
{
}
private:
};
2、bind函数
作用:
在网络编程(C/C++ 中调用系统 Socket API)里,
bind函数是将套接字与特定的 IP 地址和端口号绑定的核心函数,只有绑定后,套接字才能监听(服务端)或发起连接(在客户端中,部分场景可选)
函数原型:
cpp#include <sys/socket.h> int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数解析:
注意:
通常我们要自己填充sockaddr结构。
(2)填充sockaddr结构,且优化结构。
cpp#pragma once #include<iostream> using namespace std; #include<sys/types.h> #include<sys/socket.h> #include<strings.h> #include<cstdlib> #include <netinet/in.h> #include <arpa/inet.h> // 提供 IP 地址转换函数(如 inet_pton()、inet_ntop()、inet_addr()) const static int defaultfd = -1;//套接字默认值,-1代表创建失败 class UdpServer { public: //需要外部传入port,ip UdpServer(uint16_t port,const string& ip):_sockfd(defaultfd),_port(port),_ip(ip) {} //初始化一个socket套接字 void InitServer() { _sockfd = socket(AF_INET,SOCK_DGRAM,0); if(_sockfd < 0) { cout<<"创建失败"<<endl; exit(1); } //创建成功后,填充sockaddr结构 struct sockaddr_in local;//struct sockaddr_in 是系统提供的数据类型,local是变量,属于用户在栈上开辟的空间(类似于int a = 100;) bzero(&local,sizeof(local));//对一份空间清零 local.sin_family = AF_INET; local.sin_port = htonl(_port);//port要经过网络传输给对面,必须先到网络,而网络是大端序 //对于ip,我们需要注意两点: //a:要把字符串风格的点分十进制的IP地址转换成4字节IP地址 //b:要将主机序列转换成网络序列 //上述两点只需要一个函数可以同时进行:inet_addr local.sin_addr.s_addr = inet_addr(_ip.c_str()); } void start() { } ~UdpServer() { } private: int _sockfd; uint16_t _port; string _ip;//暂时先这样写(不是必须的) };
(3)开始绑定
cpp#pragma once #include<iostream> using namespace std; #include<sys/types.h> #include<sys/socket.h> #include<strings.h> #include<cstdlib> #include <netinet/in.h> #include <arpa/inet.h> // 提供 IP 地址转换函数(如 inet_pton()、inet_ntop()、inet_addr()) const static int defaultfd = -1;//套接字默认值,-1代表创建失败 class UdpServer { public: //需要外部传入port,ip UdpServer(uint16_t port,const string& ip):_sockfd(defaultfd),_port(port),_ip(ip) {} //初始化一个socket套接字 void InitServer() { _sockfd = socket(AF_INET,SOCK_DGRAM,0); if(_sockfd < 0) { cout<<"创建失败"<<endl; exit(1); } //创建成功后,填充sockaddr结构 struct sockaddr_in local;//struct sockaddr_in 是系统提供的数据类型,local是变量,属于用户在栈上开辟的空间(类似于int a = 100;) bzero(&local,sizeof(local));//对一份空间清零 local.sin_family = AF_INET; local.sin_port = htonl(_port);//port要经过网络传输给对面,必须先到网络,而网络是大端序 //对于ip,我们需要注意两点: //a:要把字符串风格的点分十进制的IP地址转换成4字节IP地址 //b:要将主机序列转换成网络序列 //上述两点只需要一个函数可以同时进行:inet_addr local.sin_addr.s_addr = inet_addr(_ip.c_str()); //开始bind 绑定sockfd和网络信息(IP+Port) int n = bind(_sockfd,(struct sockaddr*)&local,sizeof(local)); if(n < 0) { cout<<"绑定失败"<<endl; exit(1); } cout<<"绑定成功"<<endl; } void start() { } ~UdpServer() { } private: int _sockfd; uint16_t _port; string _ip;//暂时先这样写(不是必须的) };
(4)增加服务器是否启动的属性,默认是不启动,并且规定用户启动程序的命令行输入格式
cpp#include "UdpServer.hpp" #include <memory> //提醒用户使用方式错误 void Usage(string proc) { cout<<"Usage:\n\t"<<proc<<"local_ip local_port\n"<<endl; } int main(int argc,char* argv[]) { if(argc != 3) { Usage(argv[0]); exit(1); } //EnableScreen(); string ip = argv[1]; uint16_t port = stoi(argv[2]); unique_ptr<UdpServer> usvr = make_unique<UdpServer>(ip,port); usvr->InitServer(); usvr->start(); return 0; }
UdpServer.hpp
cppvoid start() { //服务器都是死循环,所以我们要一直运行就循环 _isrunning = true; }
3、




