1.先创建好udpServer.hpp、udpServer.cc、udpClient.hpp、udpClient.cc的框架。
#pragma once
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <functional>
#include"userManager"
#include<pthread.h>
using namespace std;
const static string defaultip = "0.0.0.0";
// typedef function<void(int,string,uint16_t,string)> func_t;
typedef void (*func_t)(int,string,uint16_t,string);
class udpServer
{
public:
udpServer(uint16_t port,func_t callback) : _port(port),_callback(callback)
{}
void init()
{}
void start()
{}
~udpServer() {}
private:
int _fd;
uint16_t _port;
string _ip;
func_t _callback;
};
#include "udpServer.hpp"
#include <memory>
#include<fstream>
using namespace std;
int main(int argc, char *argv[])
{
if (argc != 2)
{
cout << "输入错误,请重新输入" << endl;
}
uint16_t port = atoi(argv[1]);
unique_ptr<udpServer> server(new udpServer(port, callback));
server->init();
server->start();
return 0;
}
#pragma once
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <pthread.h>
using namespace std;
class udpClient
{
public:
udpClient(string serverip,uint16_t serverport):_serverip(serverip),_serverport(serverport),_fd(-1)
{}
void init()
{}
void start()
{}
~udpClient(){}
private:
int _fd;
string _serverip;
uint16_t _serverport;
pthread_t reader;//这是后期需要的,看不懂接着往下看就可以
};
#include"udpClient.hpp"
#include<memory>
using namespace std;
int main(int argc,char* argv[])
{
if(argc!=3)
{
cout<<"输入错误,请重新输入"<<endl;
}
uint16_t port = atoi(argv[2]);
string ip = argv[1];
unique_ptr<udpClient> client(new udpClient(ip,port));
client->init();
client->start();
}
2.init初始化。
//udpServer.hpp
void init()
{
// 创建套接字返回fd
_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (_fd == -1)
{
cerr << "socket error:" << errno << ":" << strerror(errno) << endl;
exit(1);
}
// 将fd和ip,port进行绑定
struct sockaddr_in sock;
sock.sin_family = AF_INET;
sock.sin_port = htons(_port);
sock.sin_addr.s_addr = INADDR_ANY;
int n = bind(_fd, (struct sockaddr *)&sock, sizeof(sock));
if (n == -1)
{
cerr << "bind error:" << errno << ":" << strerror(errno) << endl;
exit(2);
}
}
//udpClient.hpp
void init()
{
_fd = socket(AF_INET,SOCK_DGRAM,0);
if(_fd == -1)
{
cout<<"socket err:"<<errno<<":"<<strerror(errno)<<endl;
exit(1);
}
}
3.start发送、接收数据。
//udpServer.cc
void callback(int fd, string ip, uint16_t port, string messages)
{
sockaddr_in client;
socklen_t len = sizeof(client);
client.sin_family = AF_INET;
client.sin_port = htons(port);
client.sin_addr.s_addr = inet_addr(ip.c_str());
messages = "服务端的输出结果:"+messages;
sendto(fd, messages.c_str(), messages.size(), 0,(struct sockaddr *)&client, len);
}
//udpServer.hpp
void start()
{
char buffer[1024];
size_t len = sizeof(buffer);
char writer[1024];
struct sockaddr_in clientsock;
socklen_t clientlen = sizeof(clientsock);
while (1)//服务器的本质就是一个死循环
{
size_t n = recvfrom(_fd, buffer, len-1, 0, (struct sockaddr *)&clientsock, &clientlen);
if (n > 0)
{
buffer[n]=0;
string ip = inet_ntoa(clientsock.sin_addr); // uint32_t->string
uint16_t port = ntohs(clientsock.sin_port);
string messages = buffer;
cout << ip << "[" << port << "]" << "#" << messages << endl;
_callback(_fd,ip,port,messages);
}
}
}
//udpCLient.hpp
static void* readroutine(void* args)
{
pthread_detach(pthread_self());
udpClient* c = static_cast<udpClient*>(args);
sockaddr_in server;
socklen_t serverlen = sizeof(server);
while(1)
{
char buffer[1024];
int len = sizeof(buffer);
size_t n = recvfrom(c->_fd, buffer, len-1, 0, (struct sockaddr *)&server, &serverlen);
if (n > 0)
{
buffer[n]=0;
cout <<buffer << endl;
}
}
}
void start(){
pthread_create(&reader,NULL,readroutine,(void*)this);
char buffer[1024];
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(_serverport);
serveraddr.sin_addr.s_addr = inet_addr(_serverip.c_str());
while(1)
{
cin>>buffer;
ssize_t n = sendto(_fd,buffer,sizeof(buffer),0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
if(n == -1)
{
cout<<"sendto err:"<<errno<<":"<<strerror(errno)<<endl;
}
}
}
完整代码:
udpClient.cc
#include"udpClient.hpp"
#include<memory>
using namespace std;
int main(int argc,char* argv[])
{
if(argc!=3)
{
cout<<"输入错误,请重新输入"<<endl;
}
uint16_t port = atoi(argv[2]);
string ip = argv[1];
unique_ptr<udpClient> client(new udpClient(ip,port));
client->init();
client->start();
}
udpClient.hpp
#pragma once
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <pthread.h>
using namespace std;
class udpClient
{
public:
udpClient(string serverip,uint16_t serverport):_serverip(serverip),_serverport(serverport),_fd(-1)
{}
void init()
{
_fd = socket(AF_INET,SOCK_DGRAM,0);
if(_fd == -1)
{
cout<<"socket err:"<<errno<<":"<<strerror(errno)<<endl;
exit(1);
}
}
static void* readroutine(void* args)
{
pthread_detach(pthread_self());
udpClient* c = static_cast<udpClient*>(args);
sockaddr_in server;
socklen_t serverlen = sizeof(server);
while(1)
{
char buffer[1024];
int len = sizeof(buffer);
size_t n = recvfrom(c->_fd, buffer, len-1, 0, (struct sockaddr *)&server, &serverlen);
if (n > 0)
{
buffer[n]=0;
cout <<buffer << endl;
}
}
}
void start(){
pthread_create(&reader,NULL,readroutine,(void*)this);
char buffer[1024];
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(_serverport);
serveraddr.sin_addr.s_addr = inet_addr(_serverip.c_str());
while(1)
{
cin>>buffer;
ssize_t n = sendto(_fd,buffer,sizeof(buffer),0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
if(n == -1)
{
cout<<"sendto err:"<<errno<<":"<<strerror(errno)<<endl;
}
}
}
~udpClient(){}
private:
int _fd;
string _serverip;
uint16_t _serverport;
pthread_t reader;
};
udpServer.cc
#include "udpServer.hpp"
#include <memory>
#include<fstream>
using namespace std;
// 处理方式1:翻译软件
unordered_map<string, string> dictmap;
void to_map(string messages);
// 1.打开文件,按行读取
void openfile()
{
ifstream in;
in.open("dict.txt",std::ios::binary);
if(in.is_open())
{
std::string line;
while(getline(in,line))
{
to_map(line);
}
}
}
// 2.按行存到map中
void to_map(string messages)
{
size_t pos = messages.find(":");
dictmap.insert(make_pair(messages.substr(0, pos), messages.substr(pos + 1)));
}
// 3.接收传来的message并通过map查询
void translate(int fd, string ip, uint16_t port, string messages)
{
sockaddr_in client;
socklen_t len = sizeof(client);
client.sin_family = AF_INET;
client.sin_port = htons(port);
client.sin_addr.s_addr = inet_addr(ip.c_str());
if (dictmap.find(messages) != dictmap.end())
{
cout<<"messages:"<<dictmap[messages].c_str()<<endl;
sendto(fd, dictmap[messages].c_str(), dictmap[messages].size(), 0,(struct sockaddr *)&client, len);
}
else
{
string mes = "无结果";
sendto(fd, mes.c_str(), mes.size(),0, (struct sockaddr *)&client, len);
}
}
// 4.test测试文件有没有加载成功
void printdict()
{
for (auto e : dictmap)
{
cout << e.first << ":" << e.second << endl;
}
}
// 处理方式2:群聊
onlineUser onlineuser;
void group_chat(int fd, string ip, uint16_t port, string messages)
{
// 将客户端的信息传进来
onlineuser.addOnlineUser(ip, port);
onlineuser.broadcastMessage(fd, ip, port, messages);
}
// 处理方式3:最简单版本收到什么原样返回
void callback(int fd, string ip, uint16_t port, string messages)
{
sockaddr_in client;
socklen_t len = sizeof(client);
client.sin_family = AF_INET;
client.sin_port = htons(port);
client.sin_addr.s_addr = inet_addr(ip.c_str());
messages = "服务端的输出结果:"+messages;
sendto(fd, messages.c_str(), messages.size(), 0,(struct sockaddr *)&client, len);
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
cout << "输入错误,请重新输入" << endl;
}
uint16_t port = atoi(argv[1]);
//openfile();
//printdict();
unique_ptr<udpServer> server(new udpServer(port, callback));
server->init();
server->start();
return 0;
}
udpServer.hpp
#pragma once
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <functional>
#include"userManager"
#include<pthread.h>
using namespace std;
const static string defaultip = "0.0.0.0";
// typedef function<void(int,string,uint16_t,string)> func_t;
typedef void (*func_t)(int,string,uint16_t,string);
class udpServer
{
public:
udpServer(uint16_t port,func_t callback) : _port(port),_callback(callback)
{
}
void init()
{
// 创建套接字返回fd
_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (_fd == -1)
{
cerr << "socket error:" << errno << ":" << strerror(errno) << endl;
exit(1);
}
// 将fd和ip,port进行绑定
struct sockaddr_in sock;
sock.sin_family = AF_INET;
sock.sin_port = htons(_port);
sock.sin_addr.s_addr = INADDR_ANY;
int n = bind(_fd, (struct sockaddr *)&sock, sizeof(sock));
if (n == -1)
{
cerr << "bind error:" << errno << ":" << strerror(errno) << endl;
exit(2);
}
}
void start()
{
char buffer[1024];
size_t len = sizeof(buffer);
char writer[1024];
struct sockaddr_in clientsock;
socklen_t clientlen = sizeof(clientsock);
while (1)
{
size_t n = recvfrom(_fd, buffer, len-1, 0, (struct sockaddr *)&clientsock, &clientlen);
if (n > 0)
{
buffer[n]=0;
string ip = inet_ntoa(clientsock.sin_addr); // uint32_t->string
uint16_t port = ntohs(clientsock.sin_port);
string messages = buffer;
cout << ip << "[" << port << "]" << "#" << messages << endl;
_callback(_fd,ip,port,messages);
}
}
}
~udpServer() {}
private:
int _fd;
uint16_t _port;
string _ip;
pthread_t writer;
func_t _callback;
};
makefile
cc=g++
.PHONY:all
all:udpClient udpServer
udpClient:udpClient.cc
$(cc) -o $@ $^ -std=c++11 -lpthread
udpServer:udpServer.cc
$(cc) -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:
rm -f udpClient udpServer
以下是拓展的代码:
群聊:userManager
#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <functional>
using namespace std;
class User
{
public:
User(std::string ip, uint16_t port) : _ip(ip), _port(port)
{
}
~User()
{
}
std::string _ip;
int16_t _port;
};
class onlineUser
{
public:
onlineUser() {}
~onlineUser() {}
void addOnlineUser(std::string ip, uint16_t port)
{
string id = ip + "[" + std::to_string(port) + "]#";
onUser.insert(make_pair(id, User(ip, port)));
}
void offOnlineUser(std::string ip, uint16_t port)
{
string id = ip + "[" + std::to_string(port) + "]#";
onUser.erase(id);
}
void broadcastMessage(int sockfd, const string &ip, const int16_t &port, const string &messages)
{
string id = ip + "[" + std::to_string(port) + "]#";
for (auto &user : onUser)
{
if (user.first != id)
{
sockaddr_in usersock;
usersock.sin_family = AF_INET;
usersock.sin_port = htons(user.second._port);
usersock.sin_addr.s_addr = inet_addr(user.second._ip.c_str());
string sendmessage = id + messages;
sendto(sockfd, sendmessage.c_str(), sendmessage.size(), 0, (struct sockaddr *)&usersock, sizeof(usersock));
}
}
}
private:
unordered_map<string, User> onUser;
};
字典:dict.txt
hello:你好
why:为什么
so:所以
then:然后