#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <iostream>
using namespace std;
int main(){
int s1= socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
cout<<" UDP SOCKET ID:"<<s1<<endl;
int s2 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
cout<<" TCP SOCKET ID:"<<s2<<endl;
close(s1);
int s3 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
cout<<" TCP SOCKET ID:"<<s3<<endl;
close(s2);
close(s3);
return 0;
}
같은 descriptor 일지라도 완전히 다른 소켓이므로 다르다.
TCP에서 동시에 열수 있는 descriptor수는 1024
descriptor 수 조정 방법
-$ ulimit -n 1023 // 1023으로 descriptor수 증가
int s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
cout<<" TCP SOCKET ID:"<< s <<endl;
char buf[1024];
int r = send(s,buf,sizeof(buf),MSG_NOSIGNAL);
connect() 함수 없이 데이터를 쓴 경우 Broken Pipe(EPIPE) 로 실패.
os가 강제로 프로세스 종료
하지만, MSG_NOSIGNAL flag 가 종료 되는 것을 방지.
int s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
cout<<" TCP SOCKET ID:"<< s <<endl;
close(s);
char buf[1024];
int r = send(s,buf,sizeof(buf),MSG_NOSIGNAL);
소켓을 닫고 데이터를 보내려고하면 Bad file descripotr 에러 발생
socket descriptor가 종료 되어있기 때문이다.(존재 하지 않음.)
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <iostream>
using namespace std;
int main(){
int s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(s < 0){
cerr<<"socket() failed: "<< strerror(errno)<<endl;
return 1;
}
struct sockaddr_in sin;
memset(&sin,0,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
sin.sin_port = htons(10000);
//TCP connect()
if(connect(s,(struct sockaddr *)&sin, sizeof(sin)) < 0){
cerr<<"connect() failed: "<< strerror(errno)<<endl;
return 1;
}
char buf[1024];//데이터 보내기 1024bytes를 보낸 거임.
int r = send(s,buf,sizeof(buf),MSG_NOSIGNAL);
if(r < 0){
cerr<<"send() failed: "<< strerror(errno)<<endl;}
else if(r == 0){
cout<<"socket closed"<<endl;
}
else {
cout<<"Sent : "<<r<<"bytes"<<endl;
}
r = recv(s,buf,sizeof(buf),0); //데이터 수신하기
if(r < 0){
cerr<<"recv() failed: "<< strerror(errno)<<endl;}
else if(r == 0){
cerr<<"Socket Closed"<< endl; //recv() ==0 일때 연결 끊김상태
}
else{
cout<<"received : "<<r<<"bytes"<<endl;
}
close(s);
return 0;
}
active socket : 연결 맺어진 상태
클라이언트 : connect() 성공 뒤 socket
서버 : accept() 성공뒤 socket
passive socket : 연결 맺기 전 대기상태
서버측 : listen() 성공뒤 socket
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <iostream>
using namespace std;
int main(){
int passiveSock = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(10000); //server 주소 포트번호
//bind() -> 클라이언트 i
if(bind(passiveSock,(struct sockaddr *) &sin,sizeof(sin)) < 0) {
cerr<< "bind() failed: "<< strerror(errno)<<endl;
return 1;
}
//listen() passive socket
if(listen(passiveSock , 10) < 0){
cerr<<"listen() failed: "<<strerror(errno)<<endl;
return 1;
}
//accept() activer socket
memset(&sin,0,sizeof(sin));
unsigned int sin_len = sizeof(sin);
int clientSock = accept(passiveSock,(struct sockaddr *) &sin, &sin_len);
if(clientSock <0){
cerr<< "accept() failed: "<<strerror(errno)<<endl;
return 1;
}
//받을 데이터 버퍼 크기
char buf[65536];
int numrecv = recv(clientSock,buf,sizeof(buf),0); //recv()
//recv() == 0 이면 연결이 끊긴다
if(numrecv == 0){
cout<<"Socket closed"<<clientSock<< endl;
}
else if(numrecv < 0){
cerr<<"recv() failed: "<<strerror(errno)<<endl;
}
else {
cout<<"received : "<<numrecv<<"bytes , cliendsock"<< clientSock <<endl;
}
int offset = 0;
while(offset < numrecv){
int numSend = send(clientSock, buf+offset, numrecv - offset,0);
if(numSend < 0){
cerr<< "send() failed: "<<strerror(errno)<<endl;
}else{
cout<< "Sent: "<<numSend <<endl;
offset += numSend;
}
}
close(clientSock);
close(passiveSock);
}
UDP 서버 소켓 개수 -> 1개
TCP 서버 소켓 개수 -> 새로운 클라이언트 접속 passive socket, 클라이언트와 통신할 수 있는 actvie socket은 클라이언트 개수 만큼 필요.
UDP 보다 TCP 가 훨씬 많은 os 부하 발생.