udp_server.cpp
#include
#include
#include
#include
#include
#include
using namespace std;
static int port = 1997;
int main()
{
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(-1 == sockfd)
{
cout << "socket() error" << endl;
return -1;
}
struct sockaddr_in serveraddr, clientaddr;
socklen_t len = sizeof(struct sockaddr_in);
memset(&serveraddr, 0, len); // 不建议使用bzero,因为memset跨平台
memset(&clientaddr, 0, len);
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(port);
// serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); // 可以收到来自任何ip的消息
if(-1 == bind(sockfd, (struct sockaddr*)&serveraddr, len))
{
cout << "bind() error" << endl;
close(sockfd);
return -2;
}
const int buf_len = 100;
char buf[buf_len] = { 0 };
while(1)
{
memset(buf, 0, buf_len);
// 显然这个recvfrom是一个阻塞函数(当然也可以设置成非阻塞的)
// 在命令行使用 man recvfrom 可得知
// recv(sockfd, buf, len, flags);
// 相当于
// recvfrom(sockfd, buf, len, flags, NULL, NULL);
// 个人理解如果不关心是哪个ip发过来的消息就可以向上面这么用
// 第四个参数一般设为0
if(-1 == recvfrom(sockfd, buf, buf_len, 0, (struct sockaddr*)&clientaddr, &len))
{
cout << "recvfrom() error" << endl;
close(sockfd);
return -3;
}
cout << "client ip: " << inet_ntoa(clientaddr.sin_addr) << endl;
cout << "client port: " << ntohs(clientaddr.sin_port) << endl;
cout << "client msg: " << buf << endl;
cout << endl;
strcpy(buf, "I am server!");
// sendto 的第四个参数貌似也常设为0,没有深究
if(-1 == sendto(sockfd, buf, buf_len, 0, (struct sockaddr*)&clientaddr, len))
{
cout << "sendto() error" << endl;
}
}
close(sockfd);
return 0;
}
udp_client.cpp
#include
#include
#include
#include
#include
#include
using namespace std;
const int port = 1997;
const char* server_ip = "10.4.64.221";
int main()
{
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(-1 == sockfd)
{
cout << "socket() error" << endl;
return -1;
}
socklen_t len = sizeof(struct sockaddr_in);
struct sockaddr_in serveraddr;
memset(&serveraddr, 0, len);
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(port);
serveraddr.sin_addr.s_addr = inet_addr(server_ip);
const int buf_len = 100;
char buf[buf_len] = { 0 };
string s;
while(1)
{
// 使用getline来从命令行获得输入是因为即使遇到空格也会当成一个字符串
// 使用cin则达不到这样的效果
getline(cin, s);
strcpy(buf, s.c_str());
if(-1 == sendto(sockfd, buf, buf_len, 0, (struct sockaddr*)&serveraddr, len))
{
cout << "sendto() error" << endl;
close(sockfd);
return -2;
}
if(-1 == recvfrom(sockfd, buf, buf_len, 0, NULL, NULL))
{
cout << "recvfrom() error" << endl;
close(sockfd);
return -3;
}
cout << "receive from server: " << buf << endl;
}
close(sockfd);
return 0;
}
makefile
.PHONY:all
all:server client
server:udp_server.cpp
g++ -o $@ $^ -g
client:udp_client.cpp
g++ -o $@ $^ -g
.PHONY:clean
clean:
rm -rf server client
直接在命令行输入make即可编译。