struct sockaddr_in {
short sin_family; // 地址族,对于IPv4,它是 AF_INET
unsigned short sin_port; // 端口号(使用网络字节序)
struct in_addr sin_addr; // IPv4地址
char sin_zero[8]; // 填充0以使结构体与struct sockaddr的大小相同
};
command
是要执行的命令的字符串。type
是一个字符串,指定是读取命令的输出(使用 "r"
)还是向命令写入输入(使用 "w"
)。popen
返回一个 FILE *
指针,可以像处理任何其他文件流一样来处理它。如果 popen
调用失败,它将返回 NULL
#include "udpServer.hpp"
#include <memory>
using namespace std;
using namespace Server;
static void Usage(string proc)
{
cout << "\nUsage:\n\t" << proc << " local_port\n\n";
}
void handlerMessage(string clientip, uint16_t clientport, string message)
{
}
// ./udpServer port
int main(int argc, char *argv[])
{
if(argc != 2)
{
Usage(argv[0]);
exit(USAGE_ERR);
}
uint16_t port = atoi(argv[1]);
// string ip = argv[1];
std::unique_ptr<udpServer> usvr(new udpServer(handlerMessage, port));
usvr->initServer();
usvr->start();
return 0;
}
#pragma once
#include<string>
#include<iostream>
#include<sys/socket.h>
#include<strings.h>
#include<cerrno>
#include<cstring>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<functional>
static const std::string defalutIp="0.0.0.0";
static const int gnum=1024;
enum{
USAGE_ERR=1,
SOCKET_ERR,
BIND_ERR,
OPEN_ERR
};
typedef std::function<void(int,std::string,uint16_t,std::string)> func_t;
class udpServer{
public:
udpServer(const func_t &cb,uint16_t &port,const std::string ip=defalutIp):
_callback(cb),_port(port),_ip(ip),_sockfd(-1){}
void initServer(){
//1.创建socket
_sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(_sockfd==-1){
std::cerr<<"socket error"<<errno<<":"<<strerror(errno)<<std::endl;
exit(SOCKET_ERR);
}
std::cout<<"socket sucess"<<":"<<_sockfd<<std::endl;
//2.绑定port ip
struct sockaddr_in local;
bzero(&local,sizeof(local));
local.sin_family=AF_INET;
local.sin_port=htons(_port);
local.sin_addr.s_addr=INADDR_ANY;
int n=bind(_sockfd,(struct sockaddr*)&local,sizeof(local));
if(n==-1){
std::cerr<<"bind error"<<errno<<":"<<strerror(errno)<<std::endl;
exit(BIND_ERR);
}
}
void start(){
char buffer[gnum];
for(;;){
//读取数据
struct sockaddr_in peer;
socklen_t len=sizeof(peer);
ssize_t s=recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
if(s>0){
buffer[s]=0;
std::string clientip=inet_ntoa(peer.sin_addr);
uint16_t clientport=ntohs(peer.sin_port);
std::string message=buffer;
std::cout<<clientip<<"["<<clientport<<"]#"<<message<<std::endl;
//对数据处理
_callback(_sockfd,clientip,clientport,message);
}
}
}
~udpServer(){
}
private:
uint16_t _port;
std::string _ip;
int _sockfd;
func_t _callback;
};
#pragma once
#include<string>
#include<iostream>
#include<sys/socket.h>
#include<strings.h>
#include<cerrno>
#include<cstring>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
class udpClient{
public:
udpClient(const std::string&serverip,const uint16_t &serverport):
_serverip(serverip),_serverport(serverport),_sockfd(-1),_quit(false){}
void initClient(){
//创建socket
_sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(_sockfd==-1){
std::cerr<<"socket error:"<<errno<<":"<<strerror(errno)<<std::endl;
exit(2);
}
std::cout<<"socket sucess:"<<":"<<_sockfd<<std::endl;
}
void run(){
struct sockaddr_in server;
memset(&server,0,sizeof(server));
server.sin_family=AF_INET;
server.sin_addr.s_addr=inet_addr(_serverip.c_str());
server.sin_port=htons(_serverport);
std::string message;
while(!_quit){
std::cout<<"Please Enter#"<<std::endl;
std::cin>>message;
sendto(_sockfd,message.c_str(),message.size(),0,
(struct sockaddr*)&server,sizeof(server));
}
}
~udpClient(){
}
private:
int _sockfd;
std::string _serverip;
uint16_t _serverport;
bool _quit;
};
#include"udpServer.hpp"
#include<memory>
#include<fstream>
#include<signal.h>
#include<unordered_map>
using namespace std;
const string dicTxt="./dict.txt";
unordered_map<string,string>dict;
static void Usage(string proc){
cout<<"\nUsage:\n\t"<<proc<<"local_port\n\n";
}
static bool cutString(const string &target,string *s1,string *s2,const string &sep){
//apple:苹果
auto pos=target.find(sep);
if(pos==string::npos)
return false;
*s1=target.substr(0,pos);
*s2=target.substr(pos+sep.size());
return true;
}
static void initDict(){
ifstream in(dicTxt,ios::binary);
if(in.is_open()){
cerr<<"open file"<<dicTxt<<"error"<<endl;
exit(OPEN_ERR);
}
string line;
string key,value;
while(getline(in,line)){
if(cutString(line,&key,&value,":")){
dict.insert(make_pair(key,value));
}
}
in.close();
cout<<"load dict sucess"<<endl;
}
void reload(int signo){
(void)signo;
initDict();
}
static void debugPrint(){
for(auto &dt:dict){
cout<<dt.first<<"#"<<dt.second<<endl;
}
}
void handlerMessage(int sockfd,string clientip, uint16_t clientport, string message)
{
string response_message;
auto iter=dict.find(message);
if(iter==dict.end())
response_message="unknown";
else
response_message=iter->second;
//开始返回
struct sockaddr_in client;
bzero(&client,sizeof(client));
client.sin_family=AF_INET;
client.sin_port=htons(clientport);
client.sin_addr.s_addr=inet_addr(clientip.c_str());
sendto(sockfd,response_message.c_str(),response_message.size(),0,(struct sockaddr*)&client,
sizeof(client));
}
int main(int argc,char* argv[]){
if(argc!=2){
Usage(argv[0]);
exit(USAGE_ERR);
}
uint16_t port=atoi(argv[1]);
//string ip=argv[1];
unique_ptr<udpServer> usvr(new udpServer(handlerMessage,port));
usvr->initServer();
usvr->start();
return 0;
}
void execCommand(int sockfd, string clientip, uint16_t clientport, string cmd)
// {
//1. cmd解析,ls -a -l
// //2. 如果必要,可能需要fork, exec*
// if(cmd.find("rm") != string::npos || cmd.find("mv") != string::npos || cmd.find("rmdir") != string::npos)
// {
// cerr << clientip << ":" << clientport << " 正在做一个非法的操作: " << cmd << endl;
// return;
// }
// string response;
// FILE *fp = popen(cmd.c_str(), "r");
// if(fp == nullptr) response = cmd + " exec failed";
// char line[1024];
// while(fgets(line, sizeof(line), fp))
// {
// response += line;
// }
// pclose(fp);
// // 开始返回
// struct sockaddr_in client;
// bzero(&client, sizeof(client));
// client.sin_family = AF_INET;
// client.sin_port = htons(clientport);
// client.sin_addr.s_addr = inet_addr(clientip.c_str());
// sendto(sockfd, response.c_str(), response.size(), 0, (struct sockaddr*)&client, sizeof(client));
// }
int listen(int sockfd, int backlog);
sockfd
: 这是之前已经创建并绑定到某个本地地址的 socket 的文件描述符。backlog
: 这个参数指定了允许排队等待接受的传入连接请求的最大数量。换句话说,它定义了连接请求的队列长度。?
sockfd
: 这是一个监听 socket 的文件描述符,之前已经通过 bind
和 listen
函数设置为监听模式。addr
: 这是一个指向 sockaddr
结构的指针,用于接收远程主机的地址信息(即客户端的地址信息)。addrlen
: 这是一个指向 socklen_t
变量的指针,该变量在调用时包含了 addr
所指向的地址结构的大小,调用返回时则包含了实际地址结构的大小。tcpClient.hpp
#pragma once
#include<iostream>
#include<cstring>
#include<string>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#define NUM 1024
class TcpClient{
public:
TcpClient(const std::string &serverip,const uint16_t &serverport):
_sock(-1),_serverip(serverip),_serverport(serverport){}
void initClient(){
//1.创建socket
_sock=socket(AF_INET,SOCK_STREAM,0);
if(_sock<0){
std::cerr<<"sock create error"<<std::endl;
exit(2);
}
}
void start(){
struct sockaddr_in server;
memset(&server,0,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(_serverport);
server.sin_addr.s_addr=inet_addr(_serverip.c_str());
if(connect(_sock,(struct sockaddr*)&server,sizeof(server))!=0){
std::cerr<<"socket connect error"<<std::endl;
perror("Connect failed");
exit(3);
}
else{
std::string msg;
while(true){
std::cout<<"Enter#";
std::getline(std::cin,msg);
write(_sock,msg.c_str(),msg.size());
char buffer[NUM]{};
int n=read(_sock,buffer,sizeof(buffer)-1);
if(n>0){
buffer[n]=0;
std::cout<<"Server回显#"<<buffer<<std::endl;
}
else{
break;
}
}
}
}
~TcpClient(){
if(_sock>=0)
close(_sock);
}
private:
int _sock;
std::string _serverip;
uint16_t _serverport;
};
tcpClient.cc
#include"tcpClient.hpp"
#include<memory>
using namespace std;
static void Usage(string proc){
cout<<"\nUsage:\n\t"<<proc<<"serverip serverport\n\n";
}
int main(int argc,char* argv[]){
if(argc!=3){
Usage(argv[0]);
exit(1);
}
string serverip=argv[1];
uint16_t serverport=atoi(argv[2]);
unique_ptr<TcpClient> tcli(new TcpClient(serverip,serverport));
tcli->initClient();
tcli->start();
return 0;
}
tcpServer.hpp
#pragma once
#include<iostream>
#include<string>
#include<cstring>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/wait.h>
#include<signal.h>
#include<pthread.h>
#include"log.hpp"
enum{
USAGE_ERR=1,
SOCKET_ERR,
BIND_ERR,
LISTEN_ERR
};
static const uint16_t gport=8080;
static const int gbacklog=5;
class TcpServer{
public:
TcpServer(const uint16_t &port=gport):_listensock(-1),_port(gport){}
void initServer(){
//1.创建socket套接字
_listensock=socket(AF_INET,SOCK_STREAM,0);
if(_listensock<0){
logMessgae(FATAL,"create socket error");
exit(SOCKET_ERR);
}
logMessgae(NORMAL,"create socket sucess");
//2.bind绑定自己的网络信息
struct sockaddr_in local;
memset(&local,0,sizeof(local));
local.sin_family=AF_INET;
local.sin_port=htons(_port);
local.sin_addr.s_addr=INADDR_ANY;
if(bind(_listensock,(struct sockaddr*)&local,sizeof(local))<0){
logMessgae(FATAL,"bind socket error");
exit(BIND_ERR);
}
logMessgae(NORMAL,"bind socket success");
//3.设置socket为监听状态
if(listen(_listensock,gbacklog)<0){
logMessgae(FATAL,"listen socket error");
exit(LISTEN_ERR);
}
logMessgae(NORMAL,"listen socket sucess");
}
void start(){
for(;;){
//4.server获取新链接
struct sockaddr_in peer;
socklen_t len=sizeof(peer);
int sock=accept(_listensock,(struct sockaddr*)&peer,&len);
if(sock<0){
logMessgae(ERROR,"accept error,next");
continue;
}
logMessgae(NORMAL,"accept a new link");
std::cout<<"sock:"<<sock<<std::endl;
//5.通信sock
serviceIO(sock);
close(sock);
}
}
void serviceIO(int sock){
char buffer[1024]{};
while(true){
ssize_t n=read(sock,buffer,sizeof(buffer)-1);
if(n>0){
buffer[n]=0;
std::cout<<"rev message"<<std::endl;
std::string outbuffer=buffer;
outbuffer+="server[echo]";
write(sock,outbuffer.c_str(),outbuffer.size());
}
else if(n==0){
//代表client退出
logMessgae(NORMAL,"client quit,me too!");
break;
}
}
}
~TcpServer(){}
private:
int _listensock;
uint16_t _port;
};
tcpServer.cc
#include"tcpServer.hpp"
#include<memory>
using namespace std;
static void Usage(string proc){
cout<<"\nUsage:\n\t"<<proc<<"local_pro\n\n"<<endl;
}
//./tcpServer local_port
int main(int argc,char *argv[]){
if(argc!=2){
Usage(argv[0]);
exit(USAGE_ERR);
}
uint16_t port=atoi(argv[1]);
unique_ptr<TcpServer>tsvr(new TcpServer(port));
tsvr->initServer();
tsvr->start();
}
???????