リストを使ったechoサーバの作成がうまくいきません
受付中
回答 1
投稿
- 評価
- クリップ 0
- VIEW 503
現在、echoサーバを作成しています。
要件は、長い文字列が送られていた時も、リストを用いてちゃんと返すというものです。
自分でここまでプログラムを書いたのですが、以下のようにエラーが起きます。
どこに原因があるのでしょうか。
master@LAPTOP-4FABUBT7:~$ ./a.out 3875
free(): invalid pointer
Aborted (core dumped)
master@LAPTOP-4FABUBT7:~$ telnet localhost 3875
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello
OK: hello
helooooooooooooooooooooooooo
Connection closed by foreign host.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
#include <err.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#define SIZE 2048
#define L_SIZE 6//リストサイズ
/* リスト */
struct List {
char*str;
char *save;
int len;
int head;
};
/*リスト初期化*/
void init_list(struct List*list) {
list->len = L_SIZE;
list->save = (char*)malloc(sizeof(char)*L_SIZE);
list->head = 0;
list->str=(char*)malloc(sizeof(char)*L_SIZE);
}
/*ソケット準備*/
int socket_set(char*argv, struct addrinfo *hints, struct addrinfo **res) {
struct sockaddr_storage from;
socklen_t fromlen;
int error;
hints->ai_socktype = SOCK_STREAM;
hints->ai_family = AF_INET;
hints->ai_flags = AI_PASSIVE;
error = getaddrinfo(NULL, argv, hints, res);
if (error) {
errx(1, "%s", gai_strerror(error));
return 1;
}
return socket((*res)->ai_family, (*res)->ai_socktype, (*res)->ai_protocol);
}
/*拡張*/
int expand(struct List**list) {
char*new_cell;
int i;
(*list)->len *= 2;
if ((new_cell = (char*)malloc(sizeof(char)*((*list)->len))) == NULL) {
return 0;
}
for (i = 0; i < (*list)->head; i++) {
new_cell[i] = (*list)->save[i];
}
for (i = 0; i < (*list)->len; i++) {
new_cell[(*list)->head + i] = (*list)->str[i];
}
(*list)->head = (*list)->head * 2 + L_SIZE;
free((*list)->str);
free((*list)->save);
(*list)->save = new_cell;
(*list)->str = (char*)malloc(sizeof(char)*((*list)->len));
return 1;
}
void Read_Write(int *i, int *n, struct List*buf0, struct List*buf1, fd_set rfd0) {
int k;
int l;
while ((*n = read(*i, buf0->str, buf0->len)) >= buf0->len) {
if ((buf0->str[*n - 2] == 13) || (buf0->str[*n - 2] == 10)) {
break;
}
expand(&buf0);
expand(&buf1);
}
if (*n <= L_SIZE)
{
if (*n >= 2) {
buf0->str[*n - 2] = '\0';
for (k = 0; k < L_SIZE; k++) {
buf0->save[k + buf0->head] = buf0->str[k];
}
}
else if (*n == 1) {
buf0->save[buf0->head] = buf0->str[k];
}
else {
buf0->str[*n - 2] = '\0';
expand(&buf0);
expand(&buf1);
}
}
if (strncmp("quit", buf0->str,4) == 0) {
close(*i);
FD_CLR(*i, &rfd0);
}
else {
sprintf(buf1->str, "OK: %s\n", buf0->save);
l = write(*i, buf1->str, strlen(buf1->str) + 1);
if (l < 0) {
perror("write");
exit(1);
}
}
}
int main(int argc, char *argv[]) {
struct addrinfo hints, *res;
struct sockaddr_storage from;
socklen_t fromlen;
int i, n, ls, s, test;
i = n = ls = s = test = 0;
fd_set rfd, rfd0;
char buf[2048], buf2[2048];
struct List list0, list1;
if (argc != 2) {
fprintf(stderr, "usage: %s port\n", argv[0]);
exit(1);
}
memset(&hints, 0, sizeof(hints));
init_list(&list0);
init_list(&list1);
while (res != 0) {
s = socket_set(argv[1], &hints, &res);
if (s < 0) {
fprintf(stderr,"socket_erorr\n");
res = res->ai_next;
}
else {
break;
}
}
if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
perror("bind");
close(s);
return -1;
};
if (listen(s, 5) < 0) {
perror("listen");
close(s);
return -1;
}
FD_ZERO(&rfd0);
FD_SET(s, &rfd0);
while (1) {
rfd = rfd0;
if((select(FD_SETSIZE,&rfd,NULL,NULL,NULL))<0){
perror("select");
exit(1);
}
for (i = 0; i < FD_SETSIZE; i++) {
if (FD_ISSET(i, &rfd)) {
if ((ls = accept(i, NULL, NULL)) > 0) {
FD_SET(ls, &rfd0);
}
else {
Read_Write(&i,&n,&list0,&list1,rfd0);
free(list0.str);
free(list0.save);
free(list1.str);
free(list1.save);
init_list(&list0);
init_list(&list1);
}
}
}
}
close(s);
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+1
リストと言いつつ、struct List
はリスト構造のノードになっているようには見えません。
それぞれのフィールドはどういう意味なんでしょうか?
リストを使う目的が、入力バッファが足りなかった場合に継ぎ足すと言うことであれば、目的に対してコードが長すぎる気がします。struct List
の意味がわからないのでコードの中身は見てませんが。
そもそも、バッファを継ぎ足しながら、どこまで読むつもりなんでしょうか?
echoサーバーであれば、極端な話、1バイト読んで1バイト書くを、入力がクローズされるまで繰り返せばいいと思いますが。長いバッファは必要ない。
free(): invalid pointer
は、free
に与えたポインタがmalloc
で得たもので無いということですが、そこはおわかりでしょうか?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.33%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2019/08/08 03:28