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
댓글 달기