LINUX-网络编程UDP编程篇

UDP编程

对于UDP编程,我们首先需要掌握的是下图中的内容,对于编程时服务器和客户端分别需要实现的功能.

在这里插入图片描述

它是一种面向无连接的传输协议,何为面向无连接,就是在传输数据的时候,不需要判断是否与服务端建立连接就可发送数据,对方是否成功接收并不知情。这样就导致在传输的时候安全性较差,无法保证数据准确抵达,但在传输数据的效率上会稍微快一点。

头文件

以下是本次编程过程中需要用到的头文件以及宏定义

net.h

#ifndef _NET_H
#define _NET_H

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<errno.h>
#include<pthread.h>
#include <ifaddrs.h>

#endif

common.h

#ifndef _COMMON_H
#define _COMMON_H

#define SERV_PORT 5001
#define SERV_IP_ADDR "127.0.0.1"//本地回环地址
#define BACKLOG 5//请求队列大小
#define QUIT_STR "quit"

#endif

实现一个简单的UDP编程

2

客户端(client.c)

/*./client serv_ip serv_port*/
#include"net.h"
#include"common.h"

int main(int argc,char **argv){
	int fd = -1;
	int port = SERV_PORT;
    struct sockaddr_in sin;
	//输入参数判断
	if(argc != 3){
		printf("请输入: %s <serverip> <port>\n",argv[0]);
	}
        /*创建socket fd*/
        if((fd = socket(AF_INET,SOCK_DGRAM,0))<0){
                perror("socket");
                exit(-1);
        }
	if(atoi(argv[2]) < 5000 || atoi(argv[2]) > 65535){
		printf("不正确的端口号%d,用缺省端口号5001\n",port);
	}else{
		port = atoi(argv[2]);
	}
	/*连接服务器*/
	/*填充struct sockaddr_in结构体变量*/
        bzero(&sin,sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(port);
        if(inet_pton(AF_INET,argv[1],(void *)&sin.sin_addr)!= 1){
                perror("inet_pton");
                exit(-1);
        }
	/*读写数据*/
	char buf[BUFSIZ];
	while(1){
		bzero(buf,BUFSIZ);
		printf("请输入 > ");
		if(fgets(buf,BUFSIZ-1,stdin) == NULL){
			perror("fgets");
			continue;
		}
		sendto(fd,buf,strlen(buf),0,(struct sockaddr *)&sin,sizeof(sin));
		if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR))){
			printf("客户端退出!\n");
			break;
		}

	}
	/*关闭套接字*/
	close(fd);
	return 0;
}

服务器(server.c)

#include"net.h"
#include"common.h"

int main(void){
	int fd = -1;
	int port = SERV_PORT;
	int i;
	struct sockaddr_in sin;
	struct ifaddrs * ifAddrStruct=NULL;
	void * tmpAddrPtr=NULL;
	//查询本机网卡对应IP地址
	getifaddrs(&ifAddrStruct);
	puts("请选择以下网卡对应IP地址进行连接服务器:");
	while (ifAddrStruct!=NULL) {
		if (ifAddrStruct->ifa_addr->sa_family==AF_INET) { 
			// check it is IP4
			// is a valid IP4 Address
			tmpAddrPtr=&((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr;
			char addressBuffer[INET_ADDRSTRLEN];
			inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
			printf("网卡:%-5s IPV4 地址:%s\n", ifAddrStruct->ifa_name, addressBuffer);
		} 
		/*
		   else if (ifAddrStruct->ifa_addr->sa_family==AF_INET6) { 
	// check it is IP6
	// is a valid IP6 Address
	tmpAddrPtr=&((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr;
	char addressBuffer[INET6_ADDRSTRLEN];
	inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
	printf("网卡:%-5s IPV6 地址:%s\n", ifAddrStruct->ifa_name, addressBuffer);
	}
		 */
		ifAddrStruct=ifAddrStruct->ifa_next;
	}
	//先输入服务器程序的端口号
	printf("请输入端口号( >5000 ):");
	scanf("%d", &i);
	if(i < 5000 || i > 65535)
		printf("不正确的端口号%d,用缺省端口号5001\n",i);
	else
		port = i;
	/*创建socket fd*/
	if((fd = socket(AF_INET,SOCK_DGRAM,0))<0){
		perror("socket");
		exit(-1);
	}

	/*允许绑定地址快速重用*/
	int b_reuse = 1;
	setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));
	/*填充struct sockaddr_in结构体变量*/  
	bzero(&sin,sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);
	sin.sin_addr.s_addr = htonl(INADDR_ANY);
	/*绑定*/
	if(bind(fd,(struct sockaddr *)&sin,sizeof(sin))<0){
		perror("bind");
		exit(-1);
	}
	puts("等待连接....");
	char buf[BUFSIZ];
	struct sockaddr_in cin;
	socklen_t addrlen=sizeof(cin);
	while(1){
		bzero(buf,BUFSIZ);
		if(recvfrom(fd,buf,BUFSIZ-1,0,(struct sockaddr *)&cin,&addrlen) < 0){
			perror("recvfrom");
			continue;
		}
		char ipv4_addr[16];
		if(!inet_ntop(AF_INET,(void *)&cin.sin_addr,ipv4_addr,sizeof(cin))){
			perror("inet_ntop");
			exit(-1);
		}
		printf("客户端(%s:%d)输出 > :%s",ipv4_addr,ntohs(cin.sin_port),buf);

		if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR))){
			printf("客户端(%s:%d)号退出!\n",ipv4_addr,ntohs(cin.sin_port));
		}
	}
	close(fd);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值