1. 程式人生 > >嵌入式Linux網路程式設計,UDP迴圈伺服器,sendto(),recvfrom()

嵌入式Linux網路程式設計,UDP迴圈伺服器,sendto(),recvfrom()

文章目錄

在這裡插入圖片描述

1,UDP迴圈伺服器模型:

socket(...);
bind(...);
while(1){
   recvfrom(...);
   process(...);
   sendto
(...); }

2,UDP的使用場景

  1. 實時的音視訊傳輸
  2. DNS的域名解析

3,UDP資料傳送和接受sendto()、recvfrom()

ssize_t sendto(int socket, void *message, size_t length, int flags, struct sockaddr *dest_addr, socklen_t dest_len);

ssize_t recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *address, socklen_t *address_len);

這兩個函式一般在使用UDP協議時使用

4,UDP迴圈伺服器示例(可同時連線多個客戶端)

4.1,標頭檔案 net.h

#ifndef __NET_H__
#define __NET_H__

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

//#define SERV_IP_ADDR "192.168.31.100"
#define SERV_PORT 5005
//#define BACKLOG 5
#define QUIT_STR "quite"

#endif

4.2,客戶端程式碼client.c

/* UDP demo */
/*./client serv_ip serv_port */
#include "net.h"

void usage(char *s)
{
	printf("this is a UDP demo!\n");
	printf("Usage:\n\t%s <serv_ip> <serv_port>\n",s);
	printf("\tserv_ip: UDP server ip address\n");
	printf("\tserv_port: UDP server port(>5000)\n ");
}
int main(int argc, const char *argv[])
{
	int fd;
	short port;
	struct sockaddr_in sin;
	if(argc != 3)
	{
		usage((char *)argv[0]);
		exit(1);
	}
	if((port = atoi(argv[2])) < 5000)
	{
		usage((char *)argv[0]);
		exit(1);
	}
	/* 1 建立socket fd */
	if((fd = socket(AF_INET,SOCK_DGRAM,0)) < 0)//UDP程式設計
	{
		perror("socket");
		exit(-1);
	}
	
	/* 2 連線伺服器 */
	/* 2.1 填充struct sockaddr_in結構體變數*/
	bzero(&sin,sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);//轉為網路位元組序埠號
#if 0
#else
	if(inet_pton(AF_INET,argv[1],(void *)&sin.sin_addr.s_addr) < 0)
	{
		perror("inet_pton");
		goto _error1;
	}
#endif
	printf("UDP client starting ...... OK!\n");
	/* 3 讀寫*/
	char buf[BUFSIZ];
	while(1)
	{
		fprintf(stderr,"Please input the string to server:");
		bzero(buf,BUFSIZ);
		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)) == 0)
		{
			printf("client is existed!\n");
			break;
		}
	}

_error1:
	close(fd);
	return 0;
}

4.3,伺服器端程式碼server.c

#include "net.h"

int main(int argc, const char *argv[])
{
	int fd;		
	struct sockaddr_in sin;

	/* 1 建立socket fd */
	if((fd = socket(AF_INET,SOCK_DGRAM,0)) < 0)//UDP程式設計,套接字型別為SOCK_DGRAM
	{
		perror("socket");
		exit(-1);
	}

	/* 2 允許繫結地址快速重用 */ 
	int b_reuse = 1;
	setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int)); 
	
	/* 3 繫結 */
	/* 3.1 填充struct sockaddr_in 結構體變數*/
	bzero(&sin,sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(SERV_PORT);
#if 1
	/* 讓伺服器可以繫結在任意的IP上*/
	sin.sin_addr.s_addr = htonl(INADDR_ANY);
#else
	if(inet_pton(AF_INET,SERV_IP_ADDR,(void *)&sin.sin_addr.s_addr) < 0)
	{
		perror("inet_pton");
		goto _error1;
	}
#endif
	/* 3.2 繫結*/
	if(bind(fd,(struct sockaddr *)&sin,sizeof(sin)))
	{
		perror("bind");
		goto _error1;
	}
	printf("UDP server starting .... OK!\n");
	
	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 cin_ipv4_addr[16];
		if(inet_ntop(AF_INET,&cin.sin_addr.s_addr,cin_ipv4_addr,sizeof(cin_ipv4_addr)) < 0)
		{
			perror("inet_ntop");
			goto _error1;
		}

		printf("Receive from (%s:%d),Data: %s",cin_ipv4_addr,ntohs(cin.sin_port),buf);
		
		if(strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)) == 0)
		{
			printf("client (%s:%d) is existing!\n",cin_ipv4_addr,ntohs(cin.sin_port));
		}
	}
_error1:
	close(fd);
	return 0;
}