C/C++ 工程简单例子——udp通信
一、概述
以Linux环境中的udp通信举例。
工程的目录结构是这样的。
include文件夹存放各类头文件;udp_comm文件夹存放udp_comm.c(udp通道的打开、关闭相关操作);data_process文件夹存放data_process.c(数据的处理相关操作);test文件夹存放udp_recv.c和udp_send.c(测试程序)等文件。
二、工程文件
1、include文件夹
- comm_errno.h文件
//comm_errno.h
#ifndef _COMM_ERRNO_H_
#define _COMM_ERRNO_H_
#define ERR_FREE 0
#define ERR_CREATE_SOCK 0x101
#define ERR_BIND_SOCK 0x102
#define ERR_SET_SOCKOPT 0x103
#define ERR_RECVFROM 0x104
#endif
- data_process.h文件
//data_process.h
#ifndef _DATA_PROCESS_H_
#define _DATA_PROCESS_H_
//函数声明
//处理数据
int recv_data_frm_pc_process();
#endif
- dbg_color.h文件
//dbg_color.h
#ifndef _PUBLIC_DEBUG_H_
#define _PUBLIC_DEBUG_H_
#include <stdio.h>
//颜色格式:"\033[背景颜色;字体颜色m字符串\033[0m"
#define OPEN_COLOR "\033[1m"
#define BACKGROUND_COLOR_BLACK "\033[40;37m"
#define BACKGROUND_COLOR_RED "\033[41;37m"
#define BACKGROUND_COLOR_YELLOW "\033[43;37m"
#define BACKGROUND_COLOR_GREEN "\033[42;37m"
#define CLOSE_COLOR "\033[0m"
#define INFO_LOG_EN
#define ERROR_LOG_EN
#define WARNING_LOG_EN
#define RIGHT_LOG_EN
#ifdef INFO_LOG_EN
#define info_log(fmt, arg...) do{ \
printf(OPEN_COLOR BACKGROUND_COLOR_BLACK "[info_log]" CLOSE_COLOR "%s,%s():%d," fmt "\n",__FILE__, __FUNCTION__, __LINE__, ##arg); \
fflush(stdout); \
}while(0)
#else
#define info_log(fmt, arg...)
#endif
#ifdef ERROR_LOG_EN
#define error_log(fmt, arg...) do{ \
printf(OPEN_COLOR BACKGROUND_COLOR_RED "[error_log]" CLOSE_COLOR "%s,%s():%d," fmt "\n",__FILE__, __FUNCTION__, __LINE__, ##arg); \
fflush(stdout); \
}while(0)
#else
#define error_log(fmt, arg...)
#endif
#ifdef WARNING_LOG_EN
#define warning_log(fmt, arg...) do{ \
printf(OPEN_COLOR BACKGROUND_COLOR_GREEN "[warning_log]" CLOSE_COLOR "%s,%s():%d," fmt "\n",__FILE__, __FUNCTION__, __LINE__, ##arg); \
fflush(stdout); \
}while(0)
#else
#define warning_log(fmt, arg...)
#endif
#ifdef RIGHT_LOG_EN
#define right_log(fmt, arg...) do{ \
printf(OPEN_COLOR BACKGROUND_COLOR_GREEN "[right_log]" CLOSE_COLOR "%s,%s():%d," fmt "\n",__FILE__, __FUNCTION__, __LINE__, ##arg); \
fflush(stdout); \
}while(0)
#else
#define right_log(fmt, arg...)
#endif
#endif
- udp_comm.h文件
//udp_comm.h
#ifndef _UDP_COMM_H_
#define _UDP_COMM_H_
#include <stdio.h>
#define UDP_COMM_PORT 8888
#define UDP_COMM_ADDR "0.0.0.0"
#define OPEN_UDPCOMM(iRet) do{ \
iRet = open_comm_udp_sock(); \
}while(0)
#define CLOSE_UDPCOMM(iRet) do{ \
iRet = close_comm_sock(); \
}while(0)
//函数声明
//打开UDP通道
int open_comm_udp_sock();
//关闭通道
int close_comm_sock();
#endif
2、udp_comm文件夹
- udp_comm.c文件
//udp_comm.c
#include "../include/udp_comm.h"
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include "../include/comm_errno.h"
#include "../include/dbg_color.h"
extern int g_udp_comm_sock;
static int open_udp_sock(const char *ip, unsigned short port)
{
int ret = -1;
int udp_sock = 0;
/* socket */
udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
if(ERR_FREE > udp_sock)
{
error_log("udp_sock socket error: %s", strerror(errno));
ret = -ERR_CREATE_SOCK;
goto OPEN_END;
}
/* setsockopt */
int opt = 1;
ret = setsockopt(udp_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt));
if(ERR_FREE > ret)
{
error_log("udp_sock setsockopt SO_REUSEADDR error: %s", strerror(errno));
close(udp_sock);
ret = -ERR_SET_SOCKOPT;
goto OPEN_END;
}
/* bind */
struct sockaddr_in server_addr;
memset(&server_addr, 0x00, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(ip);
ret = bind(udp_sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(ERR_FREE > ret)
{
error_log("udp_sock bind error: %s", strerror(errno));
close(udp_sock);
ret = -ERR_BIND_SOCK;
goto OPEN_END;
}
ret = udp_sock;
OPEN_END:
return ret;
}
int open_comm_udp_sock()
{
g_udp_comm_sock = open_udp_sock(UDP_COMM_ADDR, UDP_COMM_PORT);
if(ERR_FREE > g_udp_comm_sock)
{
error_log("open g_udp_comm_sock error. ret = %d", g_udp_comm_sock);
return g_udp_comm_sock;
}
return ERR_FREE;
}
static void close_sock(int sock)
{
close(sock);
}
int close_comm_sock()
{
close_sock(g_udp_comm_sock);
return ERR_FREE;
}
3、data_process文件夹
- data_process.c文件
//data_process.c
#include "../include/data_process.h"
#include <errno.h>
#include <string.h>
#include "../include/dbg_color.h"
#include "../include/comm_errno.h"
extern int g_udp_comm_sock;
//函数实现
static int recv_data_frm_pc(int udp_sock)
{
int ret = -1;
unsigned char recv_buff[1024] = {0};
ret = recvfrom(udp_sock, recv_buff, sizeof(recv_buff), 0, NULL, NULL);
if(ERR_FREE > ret)
{
error_log("udp_sock recvfrom error: %s", strerror(errno));
return ERR_RECVFROM;
}
right_log("recv_buff: %s", recv_buff);
}
int recv_data_frm_pc_process()
{
int iRet = -1;
info_log("recv_data_frm_pc_process begin...");
while (1)
{
iRet = recv_data_frm_pc(g_udp_comm_sock);
if(ERR_FREE != iRet)
{
error_log("recv_data_frm_pc error. iRet = %d", iRet);
// return iRet;
}
} // <end of while(1)>
}
4、test文件夹
udp_recv.c包含了本工程的头文件;而udp_send.c并没有包含本工程的头文件,是独立的。
- udp_recv.c文件
//udp_recv.c
#include <stdio.h>
#include "../include/comm_errno.h"
#include "../include/dbg_color.h"
#include "../include/udp_comm.h"
#include "../include/data_process.h"
int g_udp_comm_sock = 0;
int main(int argc, char *argv[])
{
int iRet = -1;
OPEN_UDPCOMM(iRet);
if(ERR_FREE != iRet)
{
error_log("OPEN_UDPCOMM error: %d", iRet);
return -1;
}
recv_data_frm_pc_process();
CLOSE_UDPCOMM(iRet);
return 0;
}
- udp_send.c文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(int argc, char * argv[])
{
if(argc < 3)
{
printf("Uage:<ip> <port>\n");
return -1;
}
/* socket */
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(0 > sock)
{
perror("socket");
return -1;
}
/* sendto */
struct sockaddr_in remote_addr;
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(atoi(argv[2]));
remote_addr.sin_addr.s_addr = inet_addr(argv[1]);
bzero(remote_addr.sin_zero, 8);
unsigned char send_buff[1024] = {0};
for(;;)
{
scanf("%s", send_buff);
if(0 > sendto(sock, send_buff, sizeof(send_buff), 0, (struct sockaddr * )&remote_addr, sizeof(remote_addr)))
{
perror("sendto");
break;
}
printf("ok!\n");
}
return 0;
}
三、测试
相关代码已通过调试。
- udp_send
- udp_recv