`
从此醉
  • 浏览: 1040598 次
  • 性别: Icon_minigender_1
  • 来自: US
社区版块
存档分类
最新评论

LInux 下网络编程之一UDP通信实例详解

 
阅读更多

建议大家用eclipse for c++开发啊~~~ 好用!

至于具体的通信过程,网上一大堆。

不解释,详细解释都在代码注释里了。


客户端代码:

client.cpp

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>

#define DEST_IP "127.0.0.1"
#define SERV_PORT   8000

int main() {
	/* socket文件描述符 */
	int sock_fd;

	/* 建立udp socket */
	sock_fd = socket(AF_INET, SOCK_DGRAM, 0);

	if (sock_fd < 0) {
		perror("socket");
		exit(1);
	}

	/* 定义一个连接的地址结构体 address */
	struct sockaddr_in addr_serv;
	int len;
	memset(&addr_serv, 0, sizeof(struct sockaddr_in));

	//*************  设置协议族 即IPV4 ************//
	addr_serv.sin_family = AF_INET;

	//*************  设置连接的服务器端口 ************//
	//端口号和IP地址都是以 网络字节存储的,需要重新排序
	addr_serv.sin_port = htons(SERV_PORT); //转换为网络字节序, 小端 -> 大端

	//*************  设置连接的服务器地址 ************//
	//第0种写法,用INADDR_ANY代表服务器地址
	/* INADDR_ANY 表示不管是哪个网卡接收到数据,只要端口号对应,就会被该程序接收 */
	//addr_serv.sin_addr.s_addr = htonl(INADDR_ANY );

	//第1种地址转换方法(点分10进制,转换为in_addr_t 类型)
	addr_serv.sin_addr.s_addr = inet_addr("127.0.0.1"); //出错返回INADDR_NONE

	//第2种
	//inet_aton("127.0.0.1", &addr_serv.sin_addr);
	//*************  设置连接的服务器地址 ************//

	len = sizeof(addr_serv);


	//*************  获取本机mac地址 可忽略 ************//
	struct ifreq ifr;
	ifr.ifr_addr.sa_family = AF_INET;
	strncpy(ifr.ifr_name, "eth0", IFNAMSIZ - 1);
	ioctl(sock_fd, SIOCGIFHWADDR, &ifr);
	printf("我是客户端,我的MAC地址:");
	printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
			(unsigned char) ifr.ifr_hwaddr.sa_data[0],
			(unsigned char) ifr.ifr_hwaddr.sa_data[1],
			(unsigned char) ifr.ifr_hwaddr.sa_data[2],
			(unsigned char) ifr.ifr_hwaddr.sa_data[3],
			(unsigned char) ifr.ifr_hwaddr.sa_data[4],
			(unsigned char) ifr.ifr_hwaddr.sa_data[5]);
	//获取mac地址结束,

	int recv_num;
	int send_num;
	char send_buf[20] = "Hi, I am the client";
	char recv_buf[20]; //接收缓存

	//**************给服务器发送数据 *************//
	//相比TCP,UDP节省了connect函数,即3次握手,可以直接发送数据
	//int sendto (int socket, void *buffer. size_t size, int flags, struct sockaddr *addr, socklen_t length)
	send_num = sendto(sock_fd, send_buf, strlen(send_buf), 0,
			(struct sockaddr *) &addr_serv, len);

	printf("客户端说:%s\n", send_buf);

	if(send_num < 0){
		perror("sendto error");
		exit(1);
	}

	//**************接收服务器数据 *************//
	//int recvfrom (int socket, void *buffer, size_t size, int flags, struct sockaddr *addr, socklen_t *length-ptr)
	recv_num = recvfrom(sock_fd, recv_buf, sizeof(recv_buf), 0,
			(struct sockaddr *)&addr_serv,(socklen_t *)len);

	recv_buf[recv_num] = '\0';
	printf("客户端收到: %d bytes : %s\n", recv_num, recv_buf);
	close(sock_fd);

	return 0;
}

服务器端代码:

server.cpp

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <net/if.h>

#define SERV_PORT   8000

int main() {
	/* socket文件描述符 */
	int sock_fd;

	/* 建立udp socket */
	sock_fd = socket(AF_INET, SOCK_DGRAM, 0);

	if (sock_fd < 0) {
		perror("socket");
		exit(1);
	}

	/* 设置 address */
	struct sockaddr_in addr_serv;
	int len;
	memset(&addr_serv, 0, sizeof(struct sockaddr_in));
	addr_serv.sin_family = AF_INET;
	//htons含义:h:host n:network s:short l:long l:long
	addr_serv.sin_port = htons(SERV_PORT); //转换为网络字节序, 小端 -> 大端

	/* INADDR_ANY 表示不管是哪个网卡接收到数据,只要端口号对应,就会被该程序接收 */
	addr_serv.sin_addr.s_addr = htonl(INADDR_ANY );
	len = sizeof(addr_serv);

	/* 绑定 socket */
	// int bind (int socket, struct sockaddr *addr, socklen_t length)
	if (bind(sock_fd, (struct sockaddr *) &addr_serv, sizeof(addr_serv)) < 0) {
		perror("bind error:");
		exit(1);
	}

	int recv_num;
	int send_num;
	char send_buf[20] = "i am server!";
	char recv_buf[20]; //接收缓存
	struct sockaddr_in addr_client;

	//获取本机mac地址
	struct ifreq ifr;
	ifr.ifr_addr.sa_family = AF_INET;
	strncpy(ifr.ifr_name, "eth0", IFNAMSIZ - 1);
	ioctl(sock_fd, SIOCGIFHWADDR, &ifr);
	printf("我是服务器,我的MAC地址:");
	printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
			(unsigned char) ifr.ifr_hwaddr.sa_data[0],
			(unsigned char) ifr.ifr_hwaddr.sa_data[1],
			(unsigned char) ifr.ifr_hwaddr.sa_data[2],
			(unsigned char) ifr.ifr_hwaddr.sa_data[3],
			(unsigned char) ifr.ifr_hwaddr.sa_data[4],
			(unsigned char) ifr.ifr_hwaddr.sa_data[5]);

	//循环等待
	while (1) {
		printf("server wait:\n");

		/* recvfrom() 从基于UDP的套接口接收数据,包括发送者的IP地址。因为数据包可能来自任何主机
		 * flag=0, 常规读取,等同read()函数。 flag=MSG_PEEK,读数据但不刷新读缓冲区。MSG——OOB,读带外数据,普通数据被忽略 */
		recv_num = recvfrom(sock_fd, recv_buf, sizeof(recv_buf), 0,
				(struct sockaddr *) &addr_client, (socklen_t *) &len);

		if (recv_num < 0) {
			perror("recvfrom error:");
			exit(1);
		}

		recv_buf[recv_num] = '\0';
		printf("服务端收到: %d bytes: %s\n", recv_num, recv_buf);

		//给客户端发送数据
		send_num = sendto(sock_fd, send_buf, recv_num, 0,
				(struct sockaddr *) &addr_client, len);
		printf("服务器说:%s\n",send_buf);

		if (send_num < 0) {
			perror("sendto error:");
			exit(1);
		}
	}

	close(sock_fd);

	return 0;
}




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics