我最近在C中使用名为cwebsockets的库来处理websockets,现在可以向客户端发送消息了。问题是只要重新加载客户端的页面,应用程序就会关闭。我希望服务器端在上次连接由于重新加载而丢失之后查找新连接。
我得到的消息是send failed: connection reset by peer
,我在一些研究之后理解的是发件人没有得到客户的确认。但我该怎么处理呢?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <signal.h>
#include "websocket.h"
#define PORT 8081
#define BUF_LEN 0xFFFF
#define FILE_BUF_SIZE 30
void error(const char *msg) {
perror(msg);
exit(EXIT_FAILURE);
}
int safeSend(int clientSocket, const uint8_t *buffer, size_t bufferSize) {
#ifdef PACKET_DUMP
printf("out packet:\n");
fwrite(buffer, 1, bufferSize, stdout);
printf("\n");
#endif
ssize_t written = send(clientSocket, buffer, bufferSize, 0);
if (written == -1) {
close(clientSocket);
perror("send failed");
return EXIT_FAILURE;
}
if (written != bufferSize) {
close(clientSocket);
perror("written not all bytes");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
void clientWorker(int clientSocket) {
FILE *f;
unsigned char f_ch_a_buf[FILE_BUF_SIZE];
unsigned char f_ch_b_buf[FILE_BUF_SIZE];
short *ch_a_data = (short*)f_ch_a_buf;
short *ch_b_data = (short*)f_ch_b_buf;
int n,i;
int memfd;
void *map_base, *virt_addr;
short *ch_data;
uint8_t buffer[BUF_LEN];
memset(buffer, 0, BUF_LEN);
size_t readedLength = 0;
size_t frameSize = BUF_LEN;
enum wsState state = WS_STATE_OPENING;
uint8_t *data = NULL;
size_t dataSize = 0;
enum wsFrameType frameType = WS_INCOMPLETE_FRAME;
struct handshake hs;
nullHandshake(&hs);
uint8_t msg[BUF_LEN];
#define prepareBuffer frameSize = BUF_LEN; memset(buffer, 0, BUF_LEN);
#define initNewFrame frameType = WS_INCOMPLETE_FRAME; readedLength = 0; memset(buffer, 0, BUF_LEN);
while (frameType == WS_INCOMPLETE_FRAME) {
ssize_t readed = recv(clientSocket, buffer+readedLength, BUF_LEN-readedLength, 0);
if(readed <= 0){
if(state == WS_STATE_NORMAL){
/*
temp_raw = sys_file_read("/sys/devices/soc0/amba/f8007100.adc/iio:device0/in_temp0_raw");
temp_scale = sys_file_read("/sys/devices/soc0/amba/f8007100.adc/iio:device0/in_temp0_scale");
temp_offset = sys_file_read("/sys/devices/soc0/amba/f8007100.adc/iio:device0/in_temp0_offset");
// Formel brukt for å regne SoC temperatur: (in_temp0_raw - temp_offset)/temp_scale
dash_temp = ((temp_raw - temp_offset)/temp_scale);
*/
int EXTS[8];
int CPS[8];
int CAM[4];
int i;
for(i=0;i<8;i++){
EXTS[i] = (double)rand() / RAND_MAX;
}
for(i=0;i<8;i++){
CPS[i] = rand() % 30 + 2;
}
for(i=0;i<8;i++){
CAM[i] = rand() % 30 + 2;
}
int dash_kmt = rand() % 9 + 35;
int FSS1 = rand() % 1 + 4;
int FTWS2 = rand() % 2 + 90;
int FPFS2 = 28.5;
int MAP = rand() % 10 + 120;
int FTFS1 = rand() % 5 + 50;
int FTOS3 = rand() % 5 + 50;
int FPOS1 = rand() % 5 + 50;
int TPDS1 = rand() % 5 + 50;
int TPAS2 = rand() % 5 + 50;
int MAF = rand() % 5 + 50;
int ATFS2 = rand() % 5 + 50;
int TDC2S2 = rand() % 5 + 10;
int L1S1 = rand() % 5 + 10;
int L2S2 = rand() % 5 + 10;
int K1S1 = rand() % 5 + 10;
int K2S2 = rand() % 5 + 15;
dataSize = sprintf((char *)msg, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
dash_kmt,FSS1,FTWS2,FPFS2,MAP,EXTS[0],EXTS[1],EXTS[2],EXTS[3],EXTS[4],EXTS[5],EXTS[6],EXTS[7],
CPS[0],CPS[1],CPS[2],CPS[3],CPS[4],CPS[5],CPS[6],CPS[7],CAM[1],CAM[2],CAM[3],CAM[4],
FTFS1, FTOS3, FPOS1, TPDS1, TPAS2, MAF, ATFS2, TDC2S2, L1S1, L2S2, K1S1, K2S2
);
usleep(1000);
prepareBuffer;
wsMakeFrame(msg, dataSize, buffer, &frameSize, WS_TEXT_FRAME);
if (safeSend(clientSocket, buffer, frameSize) == EXIT_FAILURE)
break;
initNewFrame;
}
}
if(readed > 0){
readedLength+= readed;
assert(readedLength <= BUF_LEN);
if (state == WS_STATE_OPENING) {
frameType = wsParseHandshake(buffer, readedLength, &hs);
} else {
frameType = wsParseInputFrame(buffer, readedLength, &data, &dataSize);
}
if ((frameType == WS_INCOMPLETE_FRAME && readedLength == BUF_LEN) || frameType == WS_ERROR_FRAME) {
if (frameType == WS_INCOMPLETE_FRAME)
printf("buffer too small");
else
printf("error in incoming frame\n");
if (state == WS_STATE_OPENING) {
prepareBuffer;
frameSize = sprintf((char *)buffer,
"HTTP/1.1 400 Bad Request\r\n"
"%s%s\r\n\r\n",
versionField,
version);
safeSend(clientSocket, buffer, frameSize);
break;
} else {
prepareBuffer;
wsMakeFrame(NULL, 0, buffer, &frameSize, WS_CLOSING_FRAME);
if (safeSend(clientSocket, buffer, frameSize) == EXIT_FAILURE)
break;
state = WS_STATE_CLOSING;
initNewFrame;
}
}
if (state == WS_STATE_OPENING) {
assert(frameType == WS_OPENING_FRAME);
if (frameType == WS_OPENING_FRAME) {
// if resource is right, generate answer handshake and send it
if (strcmp(hs.resource, "/osc") != 0) {
frameSize = sprintf((char *)buffer, "HTTP/1.1 404 Not Found\r\n\r\n");
if (safeSend(clientSocket, buffer, frameSize) == EXIT_FAILURE)
break;
}
prepareBuffer;
wsGetHandshakeAnswer(&hs, buffer, &frameSize);
if (safeSend(clientSocket, buffer, frameSize) == EXIT_FAILURE)
break;
state = WS_STATE_NORMAL;
initNewFrame;
}
} else {
if (frameType == WS_CLOSING_FRAME) {
if (state == WS_STATE_CLOSING) {
break;
} else {
prepareBuffer;
wsMakeFrame(NULL, 0, buffer, &frameSize, WS_CLOSING_FRAME);
safeSend(clientSocket, buffer, frameSize);
break;
}
} else if (frameType == WS_TEXT_FRAME) {
uint8_t *recievedString = NULL;
recievedString = malloc(dataSize+1);
assert(recievedString);
memcpy(recievedString, data, dataSize);
recievedString[ dataSize ] = 0;
wsMakeFrame(recievedString, dataSize, buffer, &frameSize, WS_TEXT_FRAME);
if (safeSend(clientSocket, buffer, frameSize) == EXIT_FAILURE)
break;
initNewFrame;
}
}
}
}
close(clientSocket);
}
int main(int argc, char** argv)
{
int i;
int listenSocket = socket(AF_INET, SOCK_STREAM, 0);
if (listenSocket == -1) {
error("create socket failed");
}
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY;
local.sin_port = htons(PORT);
if (bind(listenSocket, (struct sockaddr *) &local, sizeof(local)) == -1) {
error("bind failed");
}
if (listen(listenSocket, 1) == -1) {
error("listen failed");
}
#ifdef DEBUG
printf("opened %s:%d\n", inet_ntoa(local.sin_addr), ntohs(local.sin_port));
#endif
while (TRUE) {
struct sockaddr_in remote;
socklen_t sockaddrLen = sizeof(remote);
int clientSocket = accept(listenSocket, (struct sockaddr*)&remote, &sockaddrLen);
if (clientSocket == -1) {
error("accept failed");
}
#ifdef DEBUG
printf("Websocket server: Connected %s:%d\n", inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));
#endif
if(fcntl(clientSocket, F_SETFL, fcntl(clientSocket, F_GETFL) | O_NONBLOCK) < 0) {
// handle error
printf("Error to put socket in non-blocking mode\n");
}
clientWorker(clientSocket);
#ifdef DEBUG
printf("Websocket server: Disconnected\n");
#endif
}
close(listenSocket);
return EXIT_SUCCESS;
}