pthread를 사용 server만드는데 오류가 계속 뜹니다.
글쓴이: kash0921 / 작성시간: 토, 2005/02/05 - 5:39오후
쓰레드를 사용해서 파일 보내주는 서버 프로그램 만드는데 자꾸 segmentation fault 가 생기는데 어떻게 해야 문제가 해결이 되는지 모르겠습니다.
pthread_create를 부를때 문제가 있는거 같은데 어찌 해야 하는지 잘 모르겠내요.
알려주시면 감사하겠습니다. 아직 완성한 프로그램은 아니지만 혹시 그 외에 문제점이라도 있으면 알려주시면 감사하겠습니다. 이 프로그램 컴파일후 실행시키면 잘 돌아가는 듯 하나 client 에서 파일 요청을 하면 segmentation fault가 뜹니다.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <netdb.h> #include <errno.h> #include <unistd.h> #include <netinet/in.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <sys/uio.h> #include <fcntl.h> #include <sys/stat.h> #include <pthread.h> #define MYPORT 6001 #define FILENAME_LEN 256 #define BUFFER_LEN (1024 * 1024) #define BACKLOG 10 /* #define THREAD_NUM */ void *serving_request(void *fd) { int new_fd, num_bytes, file_size; int byte_read, byte_written, file_requested, retval; char file_name[FILENAME_LEN]; char buf[BUFFER_LEN]; struct stat file_stat; memset(file_name,'\0', FILENAME_LEN); new_fd = *((int *) fd); pthread_detach(pthread_self()); num_bytes = recv(new_fd, file_name, FILENAME_LEN, 0); if(num_bytes == 0) { close(new_fd); break; } else if(num_bytes < 0) { perror("recv"); close(new_fd); break; } file_name[num_bytes] = '\0'; /* open a file that include path */ file_requested = open(file_name, O_RDONLY); /* open function error checking */ if(file_requested == -1) { file_size = htonl(-1); write(new_fd, &file_size, sizeof(file_size)); close(new_fd); return (NULL); } fstat(file_requested, &file_stat); file_size = 0; file_size = htonl(file_stat.st_size); if(write(new_fd, &file_size, sizeof(file_size)) == -1) { perror("write"); break; } byte_read = 0; byte_written = 0; while(byte_read < file_stat.st_size) { memset(buf, '\0', BUFFER_LEN); retval = read(file_requested, buf, BUFFER_LEN); if(retval == -1) { perror("read"); break; } byte_read += retval; retval = send(new_fd, &buf, byte_read - byte_written, 0); if(retval == -1) { perror("send"); break; } byte_written += retval; } printf("File size %d\n",ntohl(file_size)); printf("Sent all\n"); close(file_requested); close(new_fd); return (NULL); } int main() { int sockfd, *new_fd; int sin_size, thread_id; /* pthread_t p_thread[THREAD_NUM]; */ pthread_t threads; struct sockaddr_in server_addr; struct sockaddr_in client_addr; /* creating sock descriptor */ if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(MYPORT); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); memset(&(server_addr.sin_zero), '\0', 8); if(bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){ perror("bind"); exit(1); } if(listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } printf("Socket listening..\n"); sin_size = sizeof(struct sockaddr_in); while(1) { new_fd = malloc(sizeof(int)); if((*new_fd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size)) == -1) { perror("accept"); exit(1); } printf("Server: Got connection from %s\n", inet_ntoa(client_addr.sin_addr)); thread_id = pthread_create( &threads, NULL, &serving_request, new_fd); if(thread_id < 0) { perror("pthread_create"); exit(1); } /* pthread_detach(threads); */ } close(sockfd); return 0; }
Forums:
[code:1]retval = send(new_fd, &b
retval = send(new_fd, &buf, byte_read - byte_written, 0);
buf에 대한 포인터를 넘기는 것이 아니라 buf를 넘겨야 할 것 같습니다.
그리고, 쓰레드에 넘기는 void * 인자는 malloc만 있고 free는 없군요.
쓰레드를 실행하는데 처음 만나는 if 안의 break는 괴상하게 보입니다.
new_fd에 대한 write, send 가 동시에 나오는 것보다는 하나로 통일하는 것이 좋겠습니다.
처음 stat하는 순간의 크기가 도중에 줄어 들거나 늘지 않는다는 보장이 없으므로 파일을 읽는데 -1 만 확인하지 마시고, 0 도 확인하는 것이 좋습니다.
---
http://coolengineer.com
이것을 함 참조해보세요.
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
#include <netdb.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define DICE_PORT 6173
int do_debug = 0;
int do_thread = 0;
int do_stdin = 0;
int do_sleep = 0;
struct sockets {
int local;
FILE *in, *out;
};
struct sockets *get_sockets(int);
int socket_setup(void);
int debug(char *, ...);
int fail(char *, ...);
int warn(char *, ...);
int roll_die(int);
void *roll_dice(void *);
int
debug(char *fmt, ...) {
va_list ap;
int r;
va_start(ap, fmt);
if (do_debug) {
r = vfprintf(stderr, fmt, ap);
} else {
r = 0;
}
va_end(ap);
return r;
}
int
warn(char *fmt, ...) {
int r;
va_list ap;
va_start(ap, fmt);
r = vfprintf(stderr, fmt, ap);
va_end(ap);
return r;
}
int
fail(char *fmt, ...) {
int r;
va_list ap;
va_start(ap, fmt);
r = vfprintf(stderr, fmt, ap);
exit(1);
/* notreached */
va_end(ap);
return r;
}
int
roll_die(int n) {
return rand() % n + 1;
}
/* read dice on standard input, write results on standard output */
void *
roll_dice(void *v) {
struct sockets *s = v;
char inbuf[512];
/* think globally, program defensively */
if (!s || !s->out || !s->in)
return NULL;
fprintf(s->out, "enter die rolls, or q to quit\n");
while (fgets(inbuf, sizeof(inbuf), s->in) != 0) {
int dice;
int size;
if (inbuf[0] == 'q') {
fprintf(s->out, "buh-bye!\n");
if (s->local == 0) {
shutdown(fileno(s->out), SHUT_RDWR);
}
fclose(s->out);
fclose(s->in);
if (s->local == 0) {
free(s);
}
return 0;
}
if (sscanf(inbuf, "%dd%d", &dice, &size) != 2) {
fprintf(s->out, "Sorry, but I couldn't understand that.\n");
} else {
int i;
int total = 0;
for (i = 0; i < dice; ++i) {
int x = roll_die(size);
total += x;
fprintf(s->out, "%d ", x);
fflush(s->out);
if (do_sleep)
sleep(1);
}
fprintf(s->out, "= %d\n", total);
}
}
return 0;
}
int
main(int argc, char *argv[]) {
int o;
int sock;
while ((o = getopt(argc, argv, "dstS")) != -1) {
switch (o) {
case 'S':
do_sleep = 1;
break;
case 'd':
do_debug = 1;
break;
case 's':
do_stdin = 1;
break;
case 't':
do_thread = 1;
break;
}
}
if (do_stdin) {
struct sockets s;
s.local = 1;
s.in = stdin;
s.out = stdout;
if (do_thread) {
pthread_t p;
pthread_create(&p, NULL, roll_dice, (void *) &s);
} else {
roll_dice(&s);
exit(0);
}
}
sock = socket_setup();
while (1) {
struct sockets *s = get_sockets(sock);
if (s) {
if (do_thread) {
pthread_t p;
pthread_create(&p, NULL, roll_dice, (void *) s);
} else {
roll_dice(s);
exit(0);
}
}
}
return 0;
}
int
socket_setup(void) {
struct protoent *tcp_proto;
struct sockaddr_in local;
int r, s, one;
tcp_proto = getprotobyname("tcp");
if (!tcp_proto) {
fail("Can't find TCP/IP protocol: %s\n", strerror(errno));
}
s = socket(PF_INET, SOCK_STREAM, tcp_proto->p_proto);
if (s == -1) {
fail("socket: %s\n", strerror(errno));
}
one = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
memset(&local, 0, sizeof(struct sockaddr_in));
local.sin_family = AF_INET;
local.sin_port = htons(DICE_PORT);
r = bind(s, (struct sockaddr *) &local, sizeof(struct sockaddr_in));
if (r == -1) {
fail("bind: %s\n", strerror(errno));
}
r = listen(s, 5);
if (r == -1) {
fail("listen: %s\n", strerror(errno));
}
return s;
}
struct sockets *
get_sockets(int sock) {
int conn;
if ((conn = accept(sock, NULL, NULL)) < 0) {
warn("accept: %s\n", strerror(errno));
return 0;
} else {
struct sockets *s;
s = malloc(sizeof(struct sockets));
if (s == NULL) {
warn("malloc failed.\n");
return 0;
}
s->local = 0;
s->in = fdopen(conn, "r");
s->out = fdopen(conn, "w");
setlinebuf(s->in);
setlinebuf(s->out);
return s;
}
}
참조 : http://www-903.ibm.com/developerworks/kr/linux/library/l-pthred.html
댓글 달기