최근 TCP/IP Network Programming을 해야할 일이 있어서, 일을 진행하다가 개인적으로 신기했던게 있어서,
복기할 겸 글을 포스팅합니다.
1. TCP / IP
일반적으로 TCP/IP는 Byte를 전송하는 Streamer의 역활을 합니다.
따라서 모든 데이터는 Byte Stream으로 전송이 되고, 서버 및 클라이언트 상호간의 상위 데이터 프로토콜 (무엇을 보낼거냐)가 없다면
데이터를 해독할 수 없습니다.
이는 데이터를 받아서, 어떠한 데이터 캐스팅 없이, 데이터를 출력해보면 알 수 있습니다.
예를들어 C Server에서 Python Client로 어떠한 데이터를 전송하고,
이를 출력해본다면 특정한 Byte Stream으로 받는다는 것을 확인할 수 있습니다.
1-1. C Server
#include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define PORT 8888 char data[7] = "Hello!"; int serversock, clientsock; void quit(char* msg, int retval); int main(int argc, char** argv) { struct sockaddr_in server, client; int accp_sock; int addrlen = sizeof(client); int bytes; int dataSize = sizeof(data); printf("Data Size is : %d\n", dataSize); /* open socket */ if ((serversock = socket(PF_INET, SOCK_STREAM, 0)) == -1) { quit("socket() failed", 1); } /* setup server's IP and port */ memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(PORT); server.sin_addr.s_addr = INADDR_ANY; /* bind the socket */ if (bind(serversock, (const void*)&server, sizeof(server)) == -1) { quit("bind() failed", 1); } printf("start listen....\n"); // wait for connection if(listen(serversock, 10) == -1){ quit("listen() failed.", 1); } printf("client wait....\n"); accp_sock = accept(serversock, (struct sockaddr *)&client, &addrlen); if(accp_sock < 0){ quit("accept() failed", 1); } bytes = send(accp_sock, &data, dataSize, 0); if(bytes != dataSize){ fprintf(stderr, "Connection closed. bytes->[%d], dataSize->[%d]\n",bytes, dataSize); close(accp_sock); if ((accp_sock = accept(serversock, NULL, NULL)) == -1) { quit("accept() failed", 1); } } quit(NULL, 0); } void quit(char* msg, int retval) { if (retval == 0) { fprintf(stdout, (msg == NULL ? "" : msg)); fprintf(stdout, "\n"); } else { fprintf(stderr, (msg == NULL ? "" : msg)); fprintf(stderr, "\n"); } if (clientsock) close(clientsock); if (serversock) close(serversock); exit(retval); }
1-2. Python Client
from socket import * class SocketInfo(): HOST="" PORT=8888 BUFSIZE=7 ADDR=(HOST, PORT) class socketInfo(SocketInfo): HOST = "127.0.0.1" csock = socket(AF_INET, SOCK_STREAM) csock.connect(socketInfo.ADDR) print("conenct is success") commend = csock.recv(socketInfo.BUFSIZE, MSG_WAITALL) data = commend.decode("UTF-8") print("type : {}, data len : {}, data : {}, Contents : {}".format(type(commend),len(commend), commend, data)) print() csock.close() exit()
1-3. 실행화면
왼쪽부터 C Server, Python client TCP/IP Programming의 결과입니다.
서버에서 데이터를 보내면, 클라이언트에서는 Bytes타입의 데이터를 받는 것을 확인할 수 있습니다.
2. TCP/IP Connection between Python client with C Server
위에서는 C Server에서 Python Client 문자열 데이터를 보냈을 때, 해당 데이터는 Bytes 데이터로 전송되고,
잘 받았다는 것을 확인할 수 있었습니다.
그렇다면, Python Client에서 C Server로 데이터를 전송하면 어떻게 될까요?
이번에는 Python Client에서 C Server로 데이터를 전송해보도록 하겠습니다.
2-1. C Server
#include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define PORT 8888 char data[7] = "Hello!"; int serversock, clientsock; void quit(char* msg, int retval); int main(int argc, char** argv) { struct sockaddr_in server, client; int accp_sock; int addrlen = sizeof(client); int bytes; int dataSize = sizeof(data); int from_client; printf("Data Size is : %d\n", dataSize); /* open socket */ if ((serversock = socket(PF_INET, SOCK_STREAM, 0)) == -1) { quit("socket() failed", 1); } /* setup server's IP and port */ memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(PORT); server.sin_addr.s_addr = INADDR_ANY; /* bind the socket */ if (bind(serversock, (const void*)&server, sizeof(server)) == -1) { quit("bind() failed", 1); } printf("start listen....\n"); // wait for connection if(listen(serversock, 10) == -1){ quit("listen() failed.", 1); } printf("client wait....\n"); accp_sock = accept(serversock, (struct sockaddr *)&client, &addrlen); if(accp_sock < 0){ quit("accept() failed", 1); } bytes = send(accp_sock, &data, dataSize, 0); if(bytes != dataSize){ fprintf(stderr, "Connection closed. bytes->[%d], dataSize->[%d]\n",bytes, dataSize); close(accp_sock); if ((accp_sock = accept(serversock, NULL, NULL)) == -1) { quit("accept() failed", 1); } } // Data Receive // bytes re-init printf("Get Data from client\n"); bytes = 0; for(i=0; i< sizeof(from_client); i+= bytes){ if ((bytes = recv(sock, &from_client + i, sizeof(from_client) - i, 0)) == -1) { is_check = 0; quit("recv failed", 1); } } printf("Contents : %d\n, from_client"); quit(NULL, 0); } void quit(char* msg, int retval) { if (retval == 0) { fprintf(stdout, (msg == NULL ? "" : msg)); fprintf(stdout, "\n"); } else { fprintf(stderr, (msg == NULL ? "" : msg)); fprintf(stderr, "\n"); } if (clientsock) close(clientsock); if (serversock) close(serversock); exit(retval); }
2-2. Python Client
from socket import * import numpy as np class SocketInfo(): HOST="" PORT=8888 BUFSIZE=7 ADDR=(HOST, PORT) class socketInfo(SocketInfo): HOST = "127.0.0.1" csock = socket(AF_INET, SOCK_STREAM) csock.connect(socketInfo.ADDR) print("conenct is success") commend = csock.recv(socketInfo.BUFSIZE, MSG_WAITALL) data = commend.decode("UTF-8") print("type : {}, data len : {}, data : {}, Contents : {}".format(type(commend),len(commend), commend, data)) print() to_server = int(12345) to_server_bytes = bytes(to_server) print("Send Data : {}, bytes : {}".format(to_server, to_server_bytes)) sent = csock.send(to_server_bytes) csock.close() exit()
2-3. 실행결과
이런 괴상한 결과가 나오게 됩니다.
C에서의 Int형 사이즈는 4이고 Python에서 Int형 데이터를 Bytes로 컨버팅한 결과는 12345가 됩니다.
3. 해결방법
일반적으로 아래 그림과 같이 Python의 integer의 Size는 C언어의 int Size (4)와는 다릅니다.
따라서 이를 해결하려면, 서로 통신하고있는 디바이스의 자료형 데이터가 어떻게 구성되어있는지 확인하고
그에 맞춰서 데이터를 전송해야만, Server나 Client 쪽에서 데이터를 올바르게 얻어올 수 있습니다.
3-1. C Server
#include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define PORT 8888 char data[7] = "Hello!"; int serversock, clientsock; void quit(char* msg, int retval); int main(int argc, char** argv) { struct sockaddr_in server, client; int accp_sock; int addrlen = sizeof(client); int bytes; int dataSize = sizeof(data); int from_client; int i; printf("Data Size is : %d\n", dataSize); /* open socket */ if ((serversock = socket(PF_INET, SOCK_STREAM, 0)) == -1) { quit("socket() failed", 1); } /* setup server's IP and port */ memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(PORT); server.sin_addr.s_addr = INADDR_ANY; /* bind the socket */ if (bind(serversock, (const void*)&server, sizeof(server)) == -1) { quit("bind() failed", 1); } printf("start listen....\n"); // wait for connection if(listen(serversock, 10) == -1){ quit("listen() failed.", 1); } printf("client wait....\n"); accp_sock = accept(serversock, (struct sockaddr *)&client, &addrlen); if(accp_sock < 0){ quit("accept() failed", 1); } bytes = send(accp_sock, &data, dataSize, 0); if(bytes != dataSize){ fprintf(stderr, "Connection closed. bytes->[%d], dataSize->[%d]\n",bytes, dataSize); close(accp_sock); if ((accp_sock = accept(serversock, NULL, NULL)) == -1) { quit("accept() failed", 1); } } // Data Receive // bytes re-init printf("Get Data from client\n"); bytes = 0; for(i=0; i< sizeof(from_client); i+= bytes){ if ((bytes = recv(accp_sock, &from_client + i, sizeof(from_client) - i, 0)) == -1) { quit("recv failed", 1); } } printf(" from_client size : %d, Contents : %d\n", sizeof(from_client), from_client); quit(NULL, 0); } void quit(char* msg, int retval) { if (retval == 0) { fprintf(stdout, (msg == NULL ? "" : msg)); fprintf(stdout, "\n"); } else { fprintf(stderr, (msg == NULL ? "" : msg)); fprintf(stderr, "\n"); } if (clientsock) close(clientsock); if (serversock) close(serversock); exit(retval); }
3-2. Python Client
from socket import * import numpy as np class SocketInfo(): HOST="" PORT=8888 BUFSIZE=7 ADDR=(HOST, PORT) class socketInfo(SocketInfo): HOST = "127.0.0.1" csock = socket(AF_INET, SOCK_STREAM) csock.connect(socketInfo.ADDR) print("conenct is success") commend = csock.recv(socketInfo.BUFSIZE, MSG_WAITALL) data = commend.decode("UTF-8") print("type : {}, data len : {}, data : {}, Contents : {}".format(type(commend),len(commend), commend, data)) print() to_server = int(12345) right_method = to_server.to_bytes(4, byteorder='little') print("Send Data : {}, bytes len : {}, bytes : {}".format(to_server, len(right_method), right_method)) sent = csock.send(right_method) csock.close() exit()
3-3. 실행결과
'IT > Python' 카테고리의 다른 글
[MSCOCO API / Python] Install MSCOCO api (0) | 2017.12.10 |
---|---|
[ubuntu / python 2.7] graph-tool 설치 (0) | 2017.11.15 |
[numpy] numpy.pad (0) | 2017.11.13 |
[virtualenv/Uubuntu16.04] Python3 Virtualenv 설치 (0) | 2017.10.24 |
[Ubuntu16.04] Install Pycharm Community / 파이참 커뮤니티 설치 (0) | 2017.10.24 |