udpServer.cc
#include "udpServer.hpp"
void Usage(std::string proc)
{
std::cout << "Usage: " << proc << " port" <<std::endl;
}
//./udpServer ip port
int main(int argc, char *argv[])
{
if(argc != 2){//等于2是合法的
Usage(argv[0]);
exit(1);
}
udpServer *up = new udpServer(atoi(argv[1]));
up->initServer();
up->start();
delete up;
}
udpServer.hpp
#pragma once
#include<iostream>
#include<string>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
class udpServer
{
private:
std::string ip;
int port;
int sock;
public:
//构造函数
//udpServer(std::string _ip = "127.0.0.1",int _port=8080)
//:ip(_ip),port(_port)
udpServer(int _port=8080)
:port(_port)
{}
//初始化服务器
void initServer()
{//SOCK_STREAM是基于TCP的,数据传输比较有保障。SOCK_DGRAM是基于UDP的,专门用于局域网,基于广播SOCK_STREAM 是数据流,一般是tcp/ip协议的编程,SOCK_DGRAM分是数据抱,是udp协议网络编程
sock = socket(AF_INET,SOCK_DGRAM,0);//1.创建套接字
std:: cout <<"sock:"<< sock <<std:: endl;
//2.填充结构体协议,ip,port
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(port);
local.sin_addr.s_addr = INADDR_ANY;
//local.sin_addr.s_addr = inet_addr(ip.c_str());
//网络地址为INADDR_ANY,这个宏表示本地的任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP地址,这样设置可以在所有的IP地址上监听,直到与某个客户端建立了连接时才确定用哪个IP地址。
//3.绑定端口,失败则直接结束进程
if(bind(sock, (struct sockaddr*)& local,sizeof(local)) < 0)
{
std::cerr << "bind error!\n" << std::endl;
exit(1);
}
}
//echo server
//启动服务器
void start()
{
//1.创建字符串接收数据
char msg[64];
for(;;){
//定义远端addr结构体用于接收ip地址等
msg[0] = '\0';
struct sockaddr_in end_point;
socklen_t len = sizeof(end_point);
ssize_t s = recvfrom(sock,msg,sizeof(msg)-1,0,\
(struct sockaddr*)&end_point,&len);//尝试读取请求
if(s > 0){
msg[s] = '\0';
std::cout << "client#" << msg <<std:: endl;
std::string echo_string = msg;
echo_string += " [server echo]";
//返回响应给客户端
sendto (sock, echo_string.c_str(),echo_string.size(),\
0,(struct sockaddr*)&end_point,len);
}
}
}
~udpServer()
{
close(sock);
}
};
udpClient.cc
#include "udpClient.hpp"
void Usage(std::string proc)
{
std::cout <<"Usage: "<< proc << " svr_ip svr_port" << std::endl;
}
int main(int argc, char *argv[])
{
if(argc != 3){
Usage(argv[0]);
exit(1);
}
udpClient uc(argv[1], atoi(argv[2]));
uc.initClient();
uc.start();
return 0;
}
客户端不需要bind,但是需要IP和port
- 在进行bind的时候,很容易冲突!客户端无法启动
- 客户端需要唯一性,但是不需要明确必须是哪个端口号
- 但是需要IP和port:client udp,recv 和send时,系统会自动进行ip和端口号绑定
udpClient.hpp
#pragma once
#include<iostream>
#include<string>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
class udpClient
{
private:
std::string ip;//ip地址
int port;//端口号
int sock;//套接字文件描述符
public:
//ip port? server ip,port
//构造函数
udpClient(std::string _ip = "127.0.0.1",int _port=8080)
:ip(_ip),port(_port)
{}
//初始化
void initClient()
{
//创建套接字
sock = socket(AF_INET,SOCK_DGRAM,0);
std:: cout <<"sock:"<< sock <<std:: endl;
//struct sockaddr_in local;
//local.sin_family = AF_INET;
//local.sin_port = htons(port);
//local.sin_addr.s_addr = inet_addr(ip.c_str());
//if(bind(sock, (struct sockaddr*)& local,sizeof(local)) < 0)
//{
// std::cerr << "bind error!\n" << std::endl;
// exit(1);
//}
}
//echo server
void start()
{
std::string msg;
struct sockaddr_in peer;
peer.sin_family = AF_INET;
peer.sin_port = htons(port);
peer.sin_addr.s_addr = inet_addr(ip.c_str());
// char msg[64];
for(;;){
std :: cout << "Please Enter# ";
std :: cin >> msg;
if(msg == "quit")
{
break;
}
//明确客户端发送报文时给谁发
sendto(sock , msg.c_str(),msg.size(),0,(struct sockaddr*)& peer,sizeof(peer) );
char echo[128];
ssize_t s = recvfrom(sock,echo,sizeof(echo)-1, 0,nullptr,nullptr);
if(s>0)
{
echo[s] = 0;
std::cout << "server#" << echo << std::endl;
}
// msg[0] = '\0';
// struct sockaddr_in end_point;
// socklen_t len = sizeof(end_point);
// ssize_t s = recvfrom(sock,msg,sizeof(msg)-1,0,\
// (struct sockaddr*)&end_point,&len);
// if(s > 0){
// msg[s] = '\0';
// std::cout << "client#" << msg <<std:: endl;
// std::string echo_string = msg;
// echo_string += " [server echo]";
// sendto (sock, echo_string.c_str(),echo_string.size(),\
// 0,(struct sockaddr*)&end_point,len);
// }
}
}
~udpClient()
{
close(sock);
}
};