我需要用C编写一个非常基本的网络服务器。下面是我的代码。
问题在于我无法正确管理多个连接,因为当我在浏览器上打开新标签时,我总是收到消息" Connection#1",而不是" Connection#2" ,"连接#3" ...
错误在哪里?感谢
这是我的代码https://codeshare.io/a393M4 或者在这里:
#ifdef _WIN32
#include <WinSock2.h>
#define socket_t SOCKET
#else
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#define WSACleanup()
#define INVALID_SOCKET (~0)
#define SOCKET_ERROR -1
#define closesocket close
#define ioctlsocket ioctl
#define socket_t int
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
void print_time(char *buf, size_t buf_len) {
time_t rawtime;
time(&rawtime);
struct tm info;
#ifdef _WIN32
gmtime_s(&info, &rawtime);
#else
gmtime_r(&rawtime, &info);
#endif
const char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
snprintf(buf, buf_len, "%s, %i %s %i %02i:%02i:%02i GMT", days[info.tm_wday], info.tm_mday, months[info.tm_mon], 1900 + info.tm_year,
info.tm_hour, info.tm_min, info.tm_sec);
}
typedef struct sock_list {
socket_t s;
struct sock_list *next;
} sock_list;
void sock_list_insert(sock_list **list, socket_t s) {
sock_list *i = *list;
sock_list *j = *list;
sock_list *n = malloc(sizeof(sock_list));
n->s = s;
n->next = 0;
while (i) {
j = i;
i = i->next;
}
if (j) {
j->next = n;
}
else {
*list = n;
}
}
int sock_list_len(sock_list *list) {
int c = 0;
sock_list *i = list;
while (i) {
++c;
i = i->next;
}
return c;
}
int main() {
int port = 80;
#ifdef _WIN32
WSADATA wsa;
if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) {
return -1;
}
#endif
socket_t sock;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
printf("Cannot open socket (-2)\n");
WSACleanup();
return -2;
}
unsigned long mode = 1;
ioctlsocket(sock, FIONBIO, &mode); // set as non-blocking
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
if (bind(sock, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
printf("Cannot bind socket (-3)\n");
closesocket(sock);
WSACleanup();
return -3;
}
listen(sock, SOMAXCONN);
sock_list *conn_list = 0;
for (;;) {
sock_list *i = conn_list;
fd_set set;
FD_ZERO(&set);
while (i) {
FD_SET(i->s, &set);
i = i->next;
}
select(0, &set, &set, &set, 0);
struct sockaddr_in client;
memset(&client, 0, sizeof(client));
int c = sizeof(client);
socket_t ns = accept(sock, (struct sockaddr *) &client, &c);
if (ns != INVALID_SOCKET) {
printf("new sock %u\n", ns);
sock_list_insert(&conn_list, ns);
}
int count = 0;
i = conn_list;
while (i) {
++count;
int recv_sz;
char msg[4096];
char tbuf[512];
print_time(tbuf, 512);
recv_sz = recv(i->s, msg, 4096, 0);
if (recv_sz > 0) {
char html[4096];
snprintf(html, 4096, "<!DOCTYPE HTML><html><head><meta charset='utf-8'><title>Ciao</title>"
"<style type='text/css'>body {margin: 200px auto;text-align: center;color: #393939;}</style>"
"</head><body><h1>Connection %i</h1><h1>%s</h1></body></html>", count, tbuf);
snprintf(msg, 4096, "HTTP/1.1 200 OK\r\nContent-Length: %i\r\nContent-Type: text/html; charset=utf-8\r\n\r\n%s",
strlen(html),
html);
send(i->s, msg, strlen(msg), 0);
printf("send to %u\n", i->s);
}
i = i->next;
}
fflush(stdout);
#ifdef _WIN32
Sleep(1);
#else
usleep(1000);
#endif
}
closesocket(sock);
WSACleanup();
return 0;
}
答案 0 :(得分:0)
int count = 0;
i = conn_list;
while (i)
{
++count;
建议将'count'的初始化移到之前:
for (;;)
那为什么每次为每个新连接重写所有HTML页面呢?
我认为只有在找到新连接时才需要编写一个特定的HTML页面