tcp/ip 소켓 질문있습니다~!
Judicious
질문 제목 : 질문 내용 :
우선 여기서 매번 질문올려서 좋은답변받아서 잘 활용하고 있는거 감사드립니다!
제가 지금 개발하는 보드가 wifi 무선 모듈입니다 그래서 이것이 클라이언트가되고
제 pc가 서버가 되어서 데이터를 주고받는것을 테스트하고있는데요우선 제 서버쪽 코드가
#include stdio.h
#include time.h
#include winsock2.h
#pragma comment ( lib, ws2_32.lib )void main()
{
wsadata wsadata;
socket s;
socket cs;
struct sockaddr_in sin;
struct sockaddr_in cli_addr;
int size = sizeof(cli_addr);
char data[1000] = {0,};
int ret;
int cnt=1;
if( wsastartup(winsock_version, &wsadata ) != 0 )
{
printf(wsa실패, 에러코드 = %d\n, wsagetlasterror());
return;
}
s = socket( af_inet, sock_stream, ipproto_tcp );
if( s == invalid_socket) {
printf(소켓 생성실패, 에러코드 = %d\n, wsagetlasterror());
wsacleanup();
return;
}
printf(소켓생성!!!\n);
sin.sin_family = af_inet;
sin.sin_port = htons(10000);
sin.sin_addr.s_addr = htonl(addr_any);
if( bind(s, (struct sockaddr*)&sin, sizeof(sin)) == socket_error ) {
printf(바인드 실패, 에러코드 = %d\n, wsagetlasterror());
closesocket(s);
wsacleanup();
return;
}
printf(ip할당성공!!!\n);
if(listen(s,somaxconn) != 0) {
printf(리슨실패, 에러코드 = %d\n, wsagetlasterror());
closesocket(s);
wsacleanup();
return;
}
printf(listen 성공!!!\n);
cs=accept(s,(struct sockaddr*)&cli_addr,&size);
printf(accept 성공!!!\n);
if(cs == invalid_socket)
{
printf(접속 실패, 에러코드 = %d\n, wsagetlasterror());
closesocket(s);
wsacleanup();
return;
}
printf(rtd pc server!!!\n);
printf(waiting for rtd data..!\n);
while( 1 ) {
memset(data,0,sizeof(data));
ret = recv(cs,data,1000,0);
if(ret == socket_error)
{
printf(error로 들어온 recvdata : %s\n, data);
printf(error로 들어온 ret : %d\n, ret);
printf(데이터 수신 실패, 에러코드 = %u\n, wsagetlasterror());
sleep(1000);
closesocket(cs);
closesocket(s);
wsacleanup();
return;
}
printf(%s가 %d회 server로 수신되었습니다.\n,data,cnt);
sleep(1000);
send(cs,data,ret,0);
printf(%s가 %d회 rtd로 송신되었습니다.\n,data,cnt);
cnt++;//추가
}
if(closesocket(cs)!=0||closesocket(s)!=0)
{
printf(소켓 제거 실패, 에러코드 = %u\n, wsagetlasterror());
wsacleanup();
return;
}
if(wsacleanup()!=0)
{
printf(wsacleanup 실패, 에러코드 = %u\n, wsagetlasterror());
return;
}
}
이것입니다. 아주 간단한 서버입니다 그냥 데이터가 몇회주고받는지만 확인하려고만든것입니다.
근데 여기서 질문이있습니다.
제 모듈(클라이언트)에서 소켓을 닫아버릴수있는데요
그럼 저 서버쪽에선 어떻게 돌아가는게 정상인가요?
aaaa라는 데이터를 한번보내고나서
지금 강제로 닫아보면
aaaa가 1회 수신되엇습니다
aaaa가 1회 송신되었습니다
가 2회 수신되엇습니다
가 2회 송신되었습니다
가 3회 수신되엇습니다
가 3회 송신되었습니다
데이터 수신 실패, 에러코드=10053
이런식으로 되며 종료가됩니다 .
이것이 정상 동작인가요?
이렇게되면 서버쪽은 자동으로 소켓이 닫히는건가요?
-
바르고
정말 감사합니다
많은 부분이 도움이 되었습니다!
그리고 질문하나만 글더써서 더하겠씁니다! -
민아
추가적으로..이건 굳이 하시지 않아도 그다지 문제는 없다고 생각되지만..
WSAStartup이 실패하면 WSAGetLastError도 호출하실수 없는 상황입니다..
반드시 WSAStartup이 성공하셔야만 WSAGetLastError도 호출이 가능하십니다.
대신 WSAStartup이 실패할 경우 WSAStartup함수 자체가 구체적인 오류코드를 리턴합니다..
그래서
if( WSAStartup(WINSOCK_VERSION, &wsadata ) != -
기쁨해
recv가 SOCKET_ERROR가 나오더라도, 보통 상대편에서 abortive close를 한 경우
WSAGetLastError의 결과가 WSAECONNABORTED(10053)이 아니라
WSAECONNRESET(10054)이 뜬다고 알고 있습니다.
그리고 recv가 실패했든 성공했든 소켓은 마지막에 닫아줘야 합니다(즉 아직 닫힌게 아닙니다).
SOCKET_ERROR를 리턴했다고 하더라도 closesocket을 생략하시게 되면
리소스 릭입니다. -
일본드립
recv의 리턴값이 0인지 체크하는 부분도 추가하셔야 하지 않을까 싶네요.
ret = recv(cs,data,1000,0);
if(ret == SOCKET_ERROR || ret == 0)
{
//printf(\error로 들어온 recvdata : %s\\n\ -
주인님
네 하나의 클라이언트하고만 주고받을수있으면 됩니다.
지금 저상황에서 클라이언트에서 소켓을 닫아버리면
저렇게 결과가 나오는것이맞나요?? -
매미꽃
작성하신 프로그램은 오직 한 클라이언트 하고만 연결을 요청받고 데이터 처리를 한후 종료하는 심플한 서버네요. 연결 요청이 들어왔을 때 beginthread 함수를 호출해 N개의 클라이언트 요청을 처리하는 방법이 있어요. 이건 프로그램 설계 혹은 구조의 문제일 뿐이고 의도하신데로 잘 만드신거 같네요.