- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试通过 UDP 套接字将 .wav 文件从服务器发送到客户端并从客户端播放。
该文件为 48kHz 和 16 位,持续时间为 25 秒。
由于 server.c 是较大 C-RAN 代码模块中的一个小代码部分,因此我通过从标准输入传递一个 wav 文件来检查它:
./SERVER < filename.wav
// Remote Radio Head - client side
#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 <signal.h>
#include <alsa/asoundlib.h>
#include <dirent.h>
/* CONSTANTS */
#define PORT 8080
#define MAXLINE 1024
#define PAYLOAD_SIZE 128
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
/*************************************************
* DRIVER CODE *
*************************************************/
int main(int argc, char *argv[]) {
// Sockets variables
int sockfd;
char buffer1[MAXLINE];
char *data = "Hello from client, waiting for audio to playback";
struct sockaddr_in servaddr;
// ALSA playback variables
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
char *buffer2;
/*********************************************
* ALSA DRIVERS SETUP *
*********************************************/
// Open PCM device for playback.
rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (rc < 0) {
fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
exit(1);
}
// Allocate a hardware parameters object.
snd_pcm_hw_params_alloca(¶ms);
// Fill it in with default values.
snd_pcm_hw_params_any(handle, params);
// Set the desired hardware parameters.
// Interleaved mode
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
// Signed 16-bit little-endian format
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
// Two channels (stereo)
snd_pcm_hw_params_set_channels(handle, params, 2);
// bits/second sampling rate
val = 48000;
snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
// Set period size to 32 frames.
frames = 32;
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
// Write the parameters to the driver
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
exit(1);
}
// Use a buffer large enough to hold one period
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
size = frames * 4; // 2 bytes/sample, 2 channels
buffer2 = (char *) malloc(size);
// We want to loop for 25 seconds
snd_pcm_hw_params_get_period_time(params, &val, &dir);
// 25 seconds in microseconds divided by period time
loops = 25000000/val;
/*********************************************
* CREATING SOCKET FILE DESCRIPTOR *
*********************************************/
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET; //ipv4
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY; //Any server
/********************************************
* SEND MSG TO SERVER *
********************************************/
//sockfd: File descriptor of socket
//buffer: Application buffer cointaining the data to be sent
//len: Size of buffer
//flags: Bitwise OR flags to modify socket behaviour
//dest_addr: Structure containing address of destination
//addrlen: Size of dest_addr structure
sendto(sockfd, (const char *)data, strlen(data), MSG_CONFIRM, (const struct sockaddr *) &servaddr, sizeof(servaddr));
printf("Waiting for audio!!!\n");
/********************************************
* RECIEVE MSG FROM SERVER *
********************************************/
//sockfd: file descriptor of socket
//buffer: Apllication buffer in which to recieve data
//len: Size of buffer
//flags: Bitwise OR flags to modify socket behaviour
//src_addr: Structure containing source address is returned
//addrlen: Variable in which size of src_addr structure is returned
int n, len;
/* We allocate memory to store the payload of the incoming datagram. */
char *payload = (char *)malloc(PAYLOAD_SIZE*sizeof(char));
while(1){
//We receive datagram
int bytes_read = recvfrom(sockfd, (void *)payload, PAYLOAD_SIZE, MSG_WAITALL, (struct sockaddr *) &servaddr, &len);
fprintf(stderr,"r");
fflush(stderr);
// We write the datagram to stdout.
//write(1, (void *)payload, bytes_read);
//fprintf(stderr,"w");
//fflush(stderr);
while (loops > 0) {
loops--;
rc = read(sockfd, buffer2, size); //Read audio file
if (rc == 0)
{
fprintf(stderr, "end of file on input\n");
break;
}
else if (rc != size)
{
fprintf(stderr, "short read: read %d bytes\n", rc);
}
rc = snd_pcm_writei(handle, buffer2, frames);
if (rc == -EPIPE)
{
// EPIPE means underrun
fprintf(stderr, "underrun occurred\n");
snd_pcm_prepare(handle);
}
else if (rc < 0)
{
fprintf(stderr, "error from writei: %s\n",
snd_strerror(rc));
}
else if (rc != (int)frames)
{
fprintf(stderr, "short write, write %d frames\n", rc);
}
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer2);
buffer1[n] = '\0';
printf("Server : %s\n", buffer1);
}
//n = recvfrom(sockfd, (char *)buffer1, MAXLINE, MSG_WAITALL, (struct sockaddr *) &servaddr, &len);
close(sockfd); //close file descriptor
return 0;
}
// Server side implementation of UDP client-server model
#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>
//CONSTANTS
#define PORT 8080
#define MAXLINE 1024
#define PAYLOAD_SIZE 128
// Driver code
int main(int argc, char *argv[]) {
int sockfd;
char buffer[MAXLINE];
char *msg = "Hello from server, ready to send audio";
struct sockaddr_in servaddr, cliaddr;
/*********************************************
* CREATING SOCKET FILE DESCRIPTOR *
*********************************************/
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { /*AL_INET: ipv4; SOCK_DGRAM: UPD; 0: default protocol*/
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr)); //Allocate memory for structure
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;//Any client
servaddr.sin_port = htons(PORT);
/********************************************
* BIND THE SOCKET WITH THE SERVER ADDRESS *
********************************************/
//sockfd: File descriptor of socket to be binded
//addr: Structure in which address to be binded to is specified
//addrlen: Size of addr structure
if ( bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
/********************************************
* RECIEVE MSG FROM CLIENT *
********************************************/
//sockfd: file descriptor of socket
//buffer: Apllication buffer in which to recieve data
//len: Size of buffer
//flags: Bitwise OR flags to modify socket behaviour
//src_addr: Structure containing source address is returned
//addrlen: Variable in which size of src_addr structure is returned
int len, n;
len = sizeof(cliaddr); //len is value/resuslt
n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, ( struct sockaddr *) &cliaddr, &len);
buffer[n] = '\0';
printf("Client : %s\n", buffer);
/********************************************
* SEND MSG TO CLIENT *
********************************************/
//sockfd: File descriptor of socket
//buffer: Application buffer cointaining the data to be sent
//len: Size of buffer
//flags: Bitwise OR flags to modify socket behaviour
//dest_addr: Structure containing address of destination
//addrlen: Size of dest_addr structure
// We allocate memory for the datagrams payload
char *payload = (char *)malloc(PAYLOAD_SIZE*sizeof(char));
printf("Sending audio in 3, 2, 1.....\n");
while(1){
// Reading from the std in
int bytes_read = read(0, (void *)payload, PAYLOAD_SIZE);
fprintf(stderr, "r");
fflush(stderr);
if(bytes_read < 1) break;
// We write the datagram to stdout.
write(1, (void *)payload, bytes_read);
fprintf(stderr, "w");
fflush(stderr);
//Sending datagram
sendto(sockfd, (void *)payload, bytes_read, 0, (struct sockaddr *) &cliaddr, len);
fprintf(stderr, "s");
fflush(stderr);
}
//sendto(sockfd, (const char *)msg, strlen(msg), MSG_CONFIRM, (const struct sockaddr *) &cliaddr, len);
return 0;
}
最佳答案
您实现中的问题是音乐数据的传输是从服务器到客户端的一种方式。当客户端发送第一个请求时,服务器开始以最快的速度广播音频流。结果客户端会丢失一些数据包。如果只有二分之一的数据包被实际写入音频设备,那么看起来音乐的播放速度是原来的两倍。如果将所有 bytes_read
相加,您可以很容易地看到您正在丢失数据包。在客户端。它将比实际文件大小小得多。
也不清楚为什么在客户端你首先recvfrom
插入 payload
然后 read
进入 buffer2
.理论上只需要第一个操作,然后你从 payload
开始写。到音频设备。
如果您想以正确的方式实现流式传输,则需要在客户端实现适当的缓冲解决方案,并在服务器上进行一些速度限制,以避免以远高于所需的速度发送数据。
如果您想以一种简单的方式修复您的代码,一种可能性是添加一个 ACK,客户端在收到一个数据包后发送给服务器。服务器将在发送下一个数据包之前等待客户端 ACK。这或多或少会使 UDP 协议(protocol)成为 TCP 协议(protocol)。
我已经稍微修改了您的代码,以向您展示我想要的东西。使用此代码,您可以正确播放 wav 文件。它并不完美,但至少它应该让您了解您的代码有什么问题
服务器.c
// gcc -o server server.c
// Server side implementation of UDP client-server model
#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>
// CONSTANTS
#define PORT 8080
#define MAXLINE 1024
#define PAYLOAD_SIZE 2048
int main(int argc, char *argv[])
{
int sockfd;
char buffer[MAXLINE];
const char* msg = "SERVER: Sending audio complete";
struct sockaddr_in servaddr, cliaddr;
/*********************************************
* CREATING SOCKET FILE DESCRIPTOR *
*********************************************/
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
/*AL_INET: ipv4; SOCK_DGRAM: UPD; 0: default protocol*/
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr)); // Allocate memory for structure
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY; // Any client
servaddr.sin_port = htons(PORT);
/********************************************
* BIND THE SOCKET WITH THE SERVER ADDRESS *
********************************************/
//sockfd: File descriptor of socket to be binded
//addr: Structure in which address to be binded to is specified
//addrlen: Size of addr structure
if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
/********************************************
* RECIEVE MSG FROM CLIENT *
********************************************/
//sockfd: file descriptor of socket
//buffer: Apllication buffer in which to recieve data
//len: Size of buffer
//flags: Bitwise OR flags to modify socket behaviour
//src_addr: Structure containing source address is returned
//addrlen: Variable in which size of src_addr structure is returned
int len, n;
len = sizeof(cliaddr); // len is value/result
printf("Waiting for client connection...\n");
n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);
buffer[n] = '\0';
printf("%s\n", buffer);
/********************************************
* SEND MSG TO CLIENT *
********************************************/
//sockfd: File descriptor of socket
//buffer: Application buffer cointaining the data to be sent
//len: Size of buffer
//flags: Bitwise OR flags to modify socket behaviour
//dest_addr: Structure containing address of destination
//addrlen: Size of dest_addr structure
// We allocate memory for the datagrams payload
char* payload = (char*)malloc(PAYLOAD_SIZE * sizeof(char));
printf("Sending audio...\n");
while (1) {
// Reading from the stdin
int bytes_read = read(0, (void*)payload, PAYLOAD_SIZE);
if (bytes_read <= 0)
break;
// Sending datagram
sendto(sockfd, (void*)payload, bytes_read, 0, (struct sockaddr *)&cliaddr, len);
// Waiting for ACK
n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);
}
return 0;
}
// gcc -o client client.c -lasound
// Remote Radio Head - client side
#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 <alsa/asoundlib.h>
#include <dirent.h>
/* CONSTANTS */
#define PORT 8080
#define MAXLINE 1024
#define FRAME_SIZE 512
#define PAYLOAD_SIZE (FRAME_SIZE * 4)
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
int main(int argc, char *argv[])
{
// Sockets variables
int sockfd;
const char* ACK = "ack";
const char* START_BROADCAST = "CLIENT: waiting for audio to playback";
struct sockaddr_in servaddr;
// ALSA playback variables
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
/*********************************************
* ALSA DRIVERS SETUP *
*********************************************/
// Open PCM device for playback.
rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (rc < 0) {
fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
exit(1);
}
// Allocate a hardware parameters object.
snd_pcm_hw_params_alloca(¶ms);
// Fill it in with default values.
snd_pcm_hw_params_any(handle, params);
// Set the desired hardware parameters.
// Interleaved mode
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
// Signed 16-bit little-endian format
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
// Two channels (stereo)
snd_pcm_hw_params_set_channels(handle, params, 2);
// bits/second sampling rate
val = 48000;
snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
// Set period size to 32 frames.
frames = FRAME_SIZE;
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
// Write the parameters to the driver
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
exit(1);
}
/*********************************************
* CREATING SOCKET FILE DESCRIPTOR *
*********************************************/
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET; // ipv4
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY; // Any server
/********************************************
* SEND MSG TO SERVER *
********************************************/
//sockfd: File descriptor of socket
//buffer: Application buffer cointaining the data to be sent
//len: Size of buffer
//flags: Bitwise OR flags to modify socket behaviour
//dest_addr: Structure containing address of destination
//addrlen: Size of dest_addr structure
sendto(sockfd, START_BROADCAST, strlen(START_BROADCAST), 0, (const struct sockaddr *)&servaddr, sizeof(servaddr));
printf("Waiting for audio!!!\n");
/********************************************
* RECIEVE MSG FROM SERVER *
********************************************/
//sockfd: file descriptor of socket
//buffer: Apllication buffer in which to recieve data
//len: Size of buffer
//flags: Bitwise OR flags to modify socket behaviour
//src_addr: Structure containing source address is returned
//addrlen: Variable in which size of src_addr structure is returned
int n, len;
/* We allocate memory to store the payload of the incoming datagram. */
char *payload = (char *)malloc(PAYLOAD_SIZE * sizeof(char));
while (1)
{
len = PAYLOAD_SIZE;
int bytes_read = recvfrom(sockfd, (void *)payload, PAYLOAD_SIZE, MSG_WAITALL, (struct sockaddr *)&servaddr, &len);
rc = snd_pcm_writei(handle, payload, frames);
if (rc == -EPIPE) {
// EPIPE means underrun
fprintf(stderr, "underrun occurred\n");
snd_pcm_prepare(handle);
} else if (rc < 0) {
fprintf(stderr, "error from writei: %s\n",
snd_strerror(rc));
} else if (rc != (int)frames) {
fprintf(stderr, "short write, write %d frames\n", rc);
}
// Send ACK
sendto(sockfd, ACK, strlen(ACK), 0, (const struct sockaddr *)&servaddr, len);
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
close(sockfd); //close file descriptor
return 0;
}
关于c - UDP 上的 wav 文件无法在带有 Alsa-lib 的 unix 中正确播放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62103879/
我通过 spring ioc 编写了一些 Rest 应用程序。但我无法解决这个问题。这是我的异常(exception): org.springframework.beans.factory.BeanC
我对 TestNG、Spring 框架等完全陌生,我正在尝试使用注释 @Value通过 @Configuration 访问配置文件注释。 我在这里想要实现的目标是让控制台从配置文件中写出“hi”,通过
为此工作了几个小时。我完全被难住了。 这是 CS113 的实验室。 如果用户在程序(二进制计算器)结束时选择继续,我们需要使用 goto 语句来到达程序的顶部。 但是,我们还需要释放所有分配的内存。
我正在尝试使用 ffmpeg 库构建一个小的 C 程序。但是我什至无法使用 avformat_open_input() 打开音频文件设置检查错误代码的函数后,我得到以下输出: Error code:
使用 Spring Initializer 创建一个简单的 Spring boot。我只在可用选项下选择 DevTools。 创建项目后,无需对其进行任何更改,即可正常运行程序。 现在,当我尝试在项目
所以我只是在 Mac OS X 中通过 brew 安装了 qt。但是它无法链接它。当我尝试运行 brew link qt 或 brew link --overwrite qt 我得到以下信息: ton
我在提交和 pull 时遇到了问题:在提交的 IDE 中,我看到: warning not all local changes may be shown due to an error: unable
我跑 man gcc | grep "-L" 我明白了 Usage: grep [OPTION]... PATTERN [FILE]... Try `grep --help' for more inf
我有一段代码,旨在接收任何 URL 并将其从网络上撕下来。到目前为止,它运行良好,直到有人给了它这个 URL: http://www.aspensurgical.com/static/images/a
在过去的 5 个小时里,我一直在尝试在我的服务器上设置 WireGuard,但在完成所有设置后,我无法 ping IP 或解析域。 下面是服务器配置 [Interface] Address = 10.
我正在尝试在 GitLab 中 fork 我的一个私有(private)项目,但是当我按下 fork 按钮时,我会收到以下信息: No available namespaces to fork the
我这里遇到了一些问题。我是 node.js 和 Rest API 的新手,但我正在尝试自学。我制作了 REST API,使用 MongoDB 与我的数据库进行通信,我使用 Postman 来测试我的路
下面的代码在控制台中给出以下消息: Uncaught DOMException: Failed to execute 'appendChild' on 'Node': The new child el
我正在尝试调用一个新端点来显示数据,我意识到在上一组有效的数据中,它在数据周围用一对额外的“[]”括号进行控制台,我认为这就是问题是,而新端点不会以我使用数据的方式产生它! 这是 NgFor 失败的原
我正在尝试将我的 Symfony2 应用程序部署到我的 Azure Web 应用程序,但遇到了一些麻烦。 推送到远程时,我在终端中收到以下消息 remote: Updating branch 'mas
Minikube已启动并正在运行,没有任何错误,但是我无法 curl IP。我在这里遵循:https://docs.traefik.io/user-guide/kubernetes/,似乎没有提到关闭
每当我尝试docker组成任何项目时,都会出现以下错误。 我尝试过有和没有sudo 我在这台机器上只有这个问题。我可以在Mac和Amazon WorkSpace上运行相同的容器。 (myslabs)
我正在尝试 pip install stanza 并收到此消息: ERROR: No matching distribution found for torch>=1.3.0 (from stanza
DNS 解析看起来不错,但我无法 ping 我的服务。可能是什么原因? 来自集群中的另一个 Pod: $ ping backend PING backend.default.svc.cluster.l
我正在使用Hibernate 4 + Spring MVC 4当我开始 Apache Tomcat Server 8我收到此错误: Error creating bean with name 'wel
我是一名优秀的程序员,十分优秀!