拆分从套接字接收的字符数组的最佳方法
Best way to split char array received from socket
我正在编写一个简单的 HTTP 服务器,我需要解析传入的请求。
假设我读过如下一行GET /file HTTP/1.1
我需要把它分成 GET
/file
我尝试了很多方法,但似乎都无法奏效。
要注意的是,服务器在以下 while 循环中以块的形式读取传入请求:
char echoBuffer[RCVBUFSIZE];
int recvMsgSize;
if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed");
while (recvMsgSize > 0) {
if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed");
}
我在循环中尝试了以下方法:
char *token;
for (i = 0; i < 3; i++){
switch (i) {
case 0:
token = strtok(echoBuffer, "/");
printf("%s\n", token[i]);
case 1:
token = strtok(echoBuffer, "HTTP");
printf("%s\n", token[i]);
}
}
但是所有这些打印都是 GET
几次。
我尝试定义一个字符串 char *echoString
并使用 strcat()
这一切都失败了,我希望如此,因为缓冲区是一个字符数组。
那么我的选择是什么?
如上述评论所述,您需要
- 确定从
recv()
调用 返回的字符串的格式
- 标记接收到的字符串
请注意,因为任何 strtok()
系列函数(包括我下面的实现)都依赖于静态变量,它们不是线程安全的!在这里要格外小心...
#include <stdio.h>
#include <stdlib.h>
/* a dummy recv() implementation that returns the size
* of received buffer */
size_t recv_(int s, void *buf, size_t len, int flags) {
len=0;
char *tmp=buf;
for (; *tmp; ++tmp, ++len)
;
return len;
}
/* Modified version of zstring_strtok
* first call -> zstrint_strtok(char *str, char *delim, int len)
* consecutive calls -> zstrint_strtok(NULL, char *delim,0)
*/
char *zstring_strtok(char *str, const char *delim, int len) {
static char *static_str=0; /* var to store last address */
int index=0, strlength=len; /* integers for indexes */
int found = 0; /* check if delim is found */
/* delimiter cannot be NULL
* if no more char left, return NULL as well
*/
if (delim==0 || (str == 0 && static_str == 0))
return 0;
if (str == 0)
str = static_str;
/* get length of string */
if (len==0)
while(str[strlength])
strlength++;
else
strlength=len;
/* find the first occurance of delim */
for (index=0;index<strlength;index++)
if (str[index]==delim[0]) {
found=1;
break;
}
/* if delim is not contained in str, return str */
if (!found) {
static_str = 0;
return str;
}
/* check for consecutive delimiters
*if first char is delim, return delim
*/
if (str[0]==delim[0]) {
static_str = (str + 1);
return (char *)delim;
}
/* terminate the string
* this assignmetn requires char[], so str has to
* be char[] rather than *char
*/
str[index] = '[=10=]';
/* save the rest of the string */
if ((str + index + 1)!=0)
static_str = (str + index + 1);
else
static_str = 0;
return str;
}
int main()
{
char response[]="GET /file HTTP/1.1";
char *buf;
int recv_msg_size;
buf=malloc(256);
if((recv_msg_size=recv_(0,response,0,0)) > 0){
buf=zstring_strtok(response," ",recv_msg_size);
do{
printf("%s\n",buf);
} while(buf=zstring_strtok(NULL," ",0));
}
return 0;
}
zstring_strtok()
函数是 the zString library, a BSD licensed string processing library for C 中 zstring_strtok()
的修改版本。
上面的 recv_()
函数是 recv()
系统调用的虚拟替换,只是为了让示例代码对您来说更易读。在我的系统 (FreeBSD 10.2-RELEASE) 上,recv(3) 被定义为
ssize_t
recv(int s, void *buf, size_t len, int flags);
上面例子的输出是
% ./recv
GET
/file
HTTP/1.1
我正在编写一个简单的 HTTP 服务器,我需要解析传入的请求。
假设我读过如下一行GET /file HTTP/1.1
我需要把它分成 GET
/file
我尝试了很多方法,但似乎都无法奏效。
要注意的是,服务器在以下 while 循环中以块的形式读取传入请求:
char echoBuffer[RCVBUFSIZE];
int recvMsgSize;
if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed");
while (recvMsgSize > 0) {
if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed");
}
我在循环中尝试了以下方法:
char *token;
for (i = 0; i < 3; i++){
switch (i) {
case 0:
token = strtok(echoBuffer, "/");
printf("%s\n", token[i]);
case 1:
token = strtok(echoBuffer, "HTTP");
printf("%s\n", token[i]);
}
}
但是所有这些打印都是 GET
几次。
我尝试定义一个字符串 char *echoString
并使用 strcat()
这一切都失败了,我希望如此,因为缓冲区是一个字符数组。
那么我的选择是什么?
如上述评论所述,您需要
- 确定从
recv()
调用 返回的字符串的格式
- 标记接收到的字符串
请注意,因为任何 strtok()
系列函数(包括我下面的实现)都依赖于静态变量,它们不是线程安全的!在这里要格外小心...
#include <stdio.h>
#include <stdlib.h>
/* a dummy recv() implementation that returns the size
* of received buffer */
size_t recv_(int s, void *buf, size_t len, int flags) {
len=0;
char *tmp=buf;
for (; *tmp; ++tmp, ++len)
;
return len;
}
/* Modified version of zstring_strtok
* first call -> zstrint_strtok(char *str, char *delim, int len)
* consecutive calls -> zstrint_strtok(NULL, char *delim,0)
*/
char *zstring_strtok(char *str, const char *delim, int len) {
static char *static_str=0; /* var to store last address */
int index=0, strlength=len; /* integers for indexes */
int found = 0; /* check if delim is found */
/* delimiter cannot be NULL
* if no more char left, return NULL as well
*/
if (delim==0 || (str == 0 && static_str == 0))
return 0;
if (str == 0)
str = static_str;
/* get length of string */
if (len==0)
while(str[strlength])
strlength++;
else
strlength=len;
/* find the first occurance of delim */
for (index=0;index<strlength;index++)
if (str[index]==delim[0]) {
found=1;
break;
}
/* if delim is not contained in str, return str */
if (!found) {
static_str = 0;
return str;
}
/* check for consecutive delimiters
*if first char is delim, return delim
*/
if (str[0]==delim[0]) {
static_str = (str + 1);
return (char *)delim;
}
/* terminate the string
* this assignmetn requires char[], so str has to
* be char[] rather than *char
*/
str[index] = '[=10=]';
/* save the rest of the string */
if ((str + index + 1)!=0)
static_str = (str + index + 1);
else
static_str = 0;
return str;
}
int main()
{
char response[]="GET /file HTTP/1.1";
char *buf;
int recv_msg_size;
buf=malloc(256);
if((recv_msg_size=recv_(0,response,0,0)) > 0){
buf=zstring_strtok(response," ",recv_msg_size);
do{
printf("%s\n",buf);
} while(buf=zstring_strtok(NULL," ",0));
}
return 0;
}
zstring_strtok()
函数是 the zString library, a BSD licensed string processing library for C 中 zstring_strtok()
的修改版本。
上面的 recv_()
函数是 recv()
系统调用的虚拟替换,只是为了让示例代码对您来说更易读。在我的系统 (FreeBSD 10.2-RELEASE) 上,recv(3) 被定义为
ssize_t
recv(int s, void *buf, size_t len, int flags);
上面例子的输出是
% ./recv
GET
/file
HTTP/1.1