사용배포본 : 와우리눅스 7.0 까치/ 7.1 파란
VGA : MG400
M/B : ASUS P2BF
CPU : P III 700
HDD : 퀀텀 40G 5400(E-IDE)
Sound Card : SB128
LAN Card : realteck 10/100 pci
정말로 이상한 증상이 있습니다. 와우 리눅스 7.0에서
컴파일된 서버프로그램 에서 5000 port을 열어놓고있다. Client에서
접속하여 임의의 데이터를 보내면 리눅스 서버에서
6byte를 접속된 client에 보내줍니다. 꼭 동일 값을 연속하여 6byte만 보낼
때(5 byte만, 7byte만 보내면 잘됨)
윈도우 계열 pc에서 받지를 못하고. 리눅스쪽에서
netstat -tau로 보면 Send-Q (Tx buffer)에 데이터가 쌓여
있습니다. 프로그램 에서는 분명 write 또는 send를 완료
했습니다.(write나 send시 오류없이 return 값이 return됩니다.)
그런데 client쪽이 linux이면 아주 잘 받습니다.
client쪽을 간단히 짜셔도 되시고요.아니면 token2나 새롬데이터맨 에뮬레이
터 또는 telnet으로 "서버쪽ip:5000" 으로
connect하셔서 엔터나 아무 키를누르면 서버쪽으로 임의의 값이 전달되고.
서버에서 곧바로 client쪽으로 6byte를 송신 합니다.
아래에 server.c source를 첨부 합니다.
gcc -o server server.c로 컴파일 하시면 됩니다.
그런데 7.0에서 컴파일된 server실행 파일을 파란에서
실행 시키면(파란에서 컴파일 한것이 아닌데..)
아무 문제가 없이 잘 됩니다. ...
7.0의 문제 일까요?(네크웍?)
아니면 저의 어처구니 없는 실수 인가요? 정말 신기 합니다.
=== server.c === 김화중 교수님 컴퓨터 네크워크 프로그래밍
책중에 source을 일부 수정하여 이상현상이 발생하도록 만든
source입니다.
========================== 한번 해 보세요.. 이상합니다. ==
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#define MAXLINE 512
#define MAX_SOCK 64
char *escapechar = "exit";
int getmax(int);
void removeClient(int); /* 채팅 탈퇴 처리 함수 */
int maxfdp1; /* 최대 소켓번호 +1 */
int num_chat = 0; /* 채팅 참가자 수 */
int client_s[MAX_SOCK]; /* 채팅에 참가자 소켓번호 목록 */
unsigned char sendbuf[300];
//unsigned char sendbuf2[300];
int port;
int ret;
int tcp_write(int socket_no, char *str, int len);
void removeClient(int);
int tcp_write(int socket_no_, char *str_, int len_)
{
int ret;
int i = 0;
while(1)
{
ret = send(socket_no_, &str_[i], len_-i, 0);
i += ret;
if (( i>= len_) || (ret <= 0)) break;
sleep(1);
}
if (ret <= 0) return ret;
return i;
}
int main(void) {
char rline[MAXLINE];
char *start = "Connected to chat_server n";
int i, j, n;
int s, client_fd, clilen;
fd_set read_fds; /* 읽기를 감지할 소켓번호 구조체 */
struct sockaddr_in client_addr, server_addr;
/* 초기소켓 생성 */
if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
printf("Server: Can't open stream socket.");
exit(0);
}
/* server_addr 구조체의 내용 세팅 */
bzero((char *)&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(atoi("5000"));
if (bind(s,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
{
printf("Server: Can't bind local address.n");
exit(0);
}
/* 클라이언트로부터 연결요청을 기다림 */
listen(s, 5);
maxfdp1 = s + 1; /* 최대 소켓번호 +1 */
while(1) {
FD_ZERO(&read_fds);
FD_SET(s, &read_fds);
for(i=0; i<num_chat; i++) FD_SET(client_s[i], &read_fds);
maxfdp1 = getmax(s) + 1; /* maxfdp1 재 계산 */
if (select(maxfdp1, &read_fds, (fd_set *)0, (fd_set *)0,(struct
timeval *)0) < 0) {
printf("select error <= 0 n");
exit(0);
}
if(FD_ISSET(s, &read_fds)) {
clilen = sizeof(client_addr);
client_fd = accept(s, (struct sockaddr *)&client_addr,
&clilen);
if(client_fd == -1) {
printf("accept errorn");
exit(0);
}
/* 채팅 클라이언트 목록에 추가 */
client_s[num_chat] = client_fd;
num_chat++;
tcp_write(client_fd, start, strlen(start));
printf("%d번째 사용자 추가.n", num_chat);
}
/* 클라이언트가 보낸 메시지를 모든 클라이언트에게 방송 */
for(i = 0; i < num_chat; i++) {
if(FD_ISSET(client_s[i], &read_fds)) {
if((n = recv(client_s[i], rline, MAXLINE, 0)) <= 0) {
removeClient(i); /* abrupt exit */
continue;
}
/* 종료문자 처리 */
if(strstr(rline, escapechar) != NULL) {
removeClient(i); /* abrupt exit */
continue;
}
/* 모든 채팅 참가자에게 메시지 방송 */
rline[n] = '';
memset(sendbuf, 0, 300);
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
for (j = 0; j < 6; j++){
sendbuf[j] = (unsigned char)0x31;
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
for (j = 0; j < num_chat; j++) {
//send(client_s[j], rline, n, 0);
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//ret = write(client_s[j],sendbuf,6);
ret = tcp_write(client_s[j], sendbuf, 6);
printf("return:<%d>,client_s[j]:<%d>,sendbuf<%s>n",ret,client_s
[j],sendbuf);
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
}
printf("%sn", rline);
}
}
}
}
/* 채팅 탈퇴 처리 */
void removeClient(int i) {
close(client_s[i]);
if(i != num_chat-1) client_s[i] = client_s[num_chat-1];
num_chat--;
printf("채팅 참가자 1명 탈퇴. 현재 참가자 수 = %dn", num_chat);
}
/* clien_s<> 내의 최대 소켓번호 얻기(초기치는 k) */
int getmax(int k) {
int max = k;
int r;
for (r=0; r < num_chat; r++) {
if (client_s[r] > max ) max = client_s[r];
}
return max;
}
안될 조건. wowlinux 7.0(kernel 2.2.17/gcc2.96)에서 또는 hardhat2.0
(kernel 2.2.14 , 2.4.4)에서 컴파일하고
-->server.c
client는 windows계열 에뮬레이터 또는
winsock를 이용한 프로그램.
linux(server)<->linux(client)는 잘됩니다.
cheongs at netsgo.com --
정 말 이 상 하 다. 정말...