创建服务器让A,B主机完成通信。
返回值:套接字,你可以认为类似fd
参数:
创建一个套接字,类似创建一个文件标识符fd。
struct sockaddr
struct sockaddr_in
struct sockaddr_un
_in结构体中保存的是ip\port数据,而_un中保存的则是本地的数据
udp协议为了本地通信与网络通信同一套接口兼容,所以先将sockaddr_in/_un强转成sockaddr类型传入各个函数,在函数中判断前2个字节类型,来做本地通信或者网络通信。
将套接字绑定,一般来说套接字绑定都是服务器才会绑定的,客户端一般给操作系统自动分配ip与端口的。
返回值:成功0,失败-1.设置错误码
参数:
用来接收数据的接收
返回值:实际接收数据的长度,-1失败
参数
发送数据给某个主机
返回值:实际发送数据的个数,-1失败
参数
机器大小端的转换函数。h本地to转
以太网规定,网络传输数据一定是大端方式传输,所以我们的机器无论是大端还是小端,在网络中都会成为大端序列。
当是为了人能看的明白,我们的ip地址一般都是以字符串的方式呈现,这样的方式我们称为点分十进制的方式。而且传入为了的ip地址可能需要改序列,所以一批接口出现了。
这些接口将字符串转为uint32_t或者将uint32_t转为字符串
一份2个主机通过服务器可以聊天的代码
server.hpp
#pragma once
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "Log.hpp"
#include
using std::cin;
using std::cout;
using std::endl;
class udp_server
{
typedef int socket_t;
void ip_type()
{
cout << "ip:" << _ip << endl;
if (_ip == "127.0.0.1")
{
cout << "#####本地测试#####" << endl;
}
else if (_ip.empty())
{
cout << "#####开放全部ip地址#####" << endl;
}
else
{
cout << "#####指定ip地址#####" << endl;
}
}
void init_server()
{
_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (_socket < 0)
{
Log(FATAL, "socket get fail!!![%d][%s]\n", __LINE__, __TIME__);
exit(1);
}
struct sockaddr_in ip_port;
bzero(&ip_port, sizeof(ip_port));
ip_port.sin_family = AF_INET;
ip_port.sin_addr.s_addr = _ip.empty() ? INADDR_ANY : inet_addr(_ip.c_str());
ip_port.sin_port = htons(_port);
if (bind(_socket, (struct sockaddr *)&ip_port, sizeof(ip_port)) < 0)
{
Log(FATAL, "bind fail!!![%d][%s]\n", __LINE__, __TIME__);
exit(2);
}
Log(NORMAL, "udp init success!!![%d][%s]\n", __LINE__, __TIME__);
}
public:
udp_server(uint16_t port, std::string ip = "") : _ip(ip), _port(port) {}
udp_server() {}
void activate()
{
init_server();
ip_type();
while (1)
{
char buff[1024] = {0};
// cout<<"buff size: "<= 0)
{
buff[end] = '\0';
printf("[%s:%d]clint say# %s\n", inet_ntoa(client_ip_port.sin_addr), ntohs(client_ip_port.sin_port), buff);
sprintf(retbuff,"[%s:%d]clint say# %s", inet_ntoa(client_ip_port.sin_addr), ntohs(client_ip_port.sin_port), buff);
}
else
{
Log(WARINNG, "recvfrom Message have fail [%d][%s]\n", __LINE__, __TIME__);
}
//处理数据。
char key[64];
snprintf(key,sizeof(key),"%s-%u",inet_ntoa(client_ip_port.sin_addr),client_ip_port.sin_port);
auto it = _users.find(key);
if(it==_users.end())
{
cout< _users;
};
server.cpp
#include "server.hpp"
#include
using std::shared_ptr;
void SERVERUER()
{
std::cout<<"./server + ip + port"< server_ptr(new udp_server(port));
server_ptr->activate();
}
else
{
in_port_t port=atoi(argv[2]);
std::string ip=argv[1];
shared_ptr server_ptr(new udp_server(port,ip));
server_ptr->activate();
}
}
else
{
SERVERUER();
}
return 0;
}
client.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "Log.hpp"
#include
using std::cin;
using std::cout;
using std::endl;
typedef int socket_t;
void CLIENTUER()
{
std::cout << "./client + ip + port" << std::endl;
}
void *thread_func(void *ages)
{
socket_t *_socket = (socket_t*)ages;
char get_messages[102];
struct sockaddr_in temp;
bzero((void *)&temp, sizeof(temp));
socklen_t len(sizeof temp);
while (1)
{
ssize_t end = recvfrom(*_socket, get_messages, sizeof(get_messages) - 1, 0, (struct sockaddr *)&temp, &len);
if (end >= 0)
{
get_messages[end] = 0;
std::cout<< get_messages << std::endl;
}
}
return nullptr;
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
CLIENTUER();
exit(1);
}
socket_t _socket = socket(AF_INET, SOCK_DGRAM, 0);
pthread_t tid;
pthread_create(&tid,nullptr,thread_func,(void*)&_socket);
std::string messages;
struct sockaddr_in server_ip_port;
bzero(&server_ip_port, sizeof(server_ip_port));
server_ip_port.sin_family = AF_INET;
server_ip_port.sin_addr.s_addr = inet_addr(argv[1]);
server_ip_port.sin_port = htons(atoi(argv[2]));
socklen_t len = sizeof(server_ip_port);
while (1)
{
fflush(stdout);
std::getline(std::cin, messages);
sendto(_socket, messages.c_str(), messages.size(), 0, (struct sockaddr *)&server_ip_port, len);
}
return 0;
}