728x90
반응형
1. 목적
- [프로젝트> 그룹> 커뮤니케이션] 중 화상 회의/영상 채팅 기술을 구현하기 위한 연습코드
- TCP/IP 연결이 성립된 상태에서 1:1로 실시간 단방향 영상 전송을 구현
2. 구성
- 노트북 카메라 연결 -> 영상 캡쳐 후 파일 저장 -> 저장된 이미지 파일을 TCP/IP 소켓으로 전송해줌 -> 클라이언트에서는 파일로 받은 후 이미지를 보여줌
- 언어는 C/C++, 네트워크는 윈도우 소켓, 형식은 윈도우 실행파일(exe), 라이브러리는 동적로딩으로 활용(DLL 파일 따로 필요)
- 베이스 코드 : https://hwan001.tistory.com/54?category=747955
3. 코드
// windows socket
#include <winsock2.h>
// windows
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// opencv
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "ws2_32.lib")
// Socket
#define IP "127.0.0.1"
#define PORT 6667
#define BUFSIZE 44000
void server();
void client(char *server_ip);
void client_send(SOCKET *sock);
void server_recv(SOCKET *client_sock);
int main() {
int sel;
char server_ip[21];
printf("1: server\n2:client\n3.tmp file clear >");
scanf_s("%d", &sel);
switch (sel)
{
case 1: // 서버로 수신
server();
break;
case 2: // 클라이언트로 전송
printf("Server IP : ");
scanf_s("%s", server_ip, 21);
if (!strcmp(server_ip, "test")) {
strcpy(server_ip, IP);
}
printf("%s\n", server_ip);
client(server_ip);
break;
case 3: // 임시 파일 삭제
remove("recv.jpg");
remove("tmp.jpg");
break;
default:
break;
}
return 0;
}
void client(char *server_ip) {
// WSA 초기화
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
// 소켓 만들기
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addr;
// 소켓 설정
ZeroMemory(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(server_ip);
addr.sin_port = htons(PORT);
// TCP 연결 시도
connect(sock, (SOCKADDR *)&addr, sizeof(addr));
// 영상 전송
client_send(&sock);
// 마무리
closesocket(sock);
WSACleanup();
remove("tmp.jpg");
}
void server() {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
// 소켓 만들기
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addr;
// 소켓 설정
ZeroMemory(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(PORT);
bind(sock, (SOCKADDR *)&addr, sizeof(addr));
listen(sock, 2);
printf("listen ok\n");
// 클라이언트 연결 요청 수락
SOCKADDR_IN client_addr;
ZeroMemory(&client_addr, sizeof(client_addr));
int nlen = sizeof(client_addr);
SOCKET client_sock = accept(sock, (SOCKADDR *)&client_addr, &nlen);
// TCP 연결 수립
printf("clinet IP : %s\n", inet_ntoa(client_addr.sin_addr));
// 영상 수신
server_recv(&client_sock);
// 마무리
closesocket(sock);
WSACleanup();
remove("recv.jpg");
}
// server function
void server_recv(SOCKET *client_sock) {
FILE *fp = NULL;
char buf[BUFSIZE];
char buf2[BUFSIZE];
Mat image;
while (1) {
// 이미지 파일 수신
ZeroMemory(buf, NULL);
fopen_s(&fp, "recv.jpg", "wb");
// 버퍼 채우기
recv(*client_sock, buf, sizeof(buf), 0);
fwrite(buf, BUFSIZE, 1, fp);
// 버퍼를 두번 받으면 딜레이가 사라진다??
recv(*client_sock, buf2, sizeof(buf2), 0);
fwrite(buf2, BUFSIZE, 1, fp);
fclose(fp);
// 이미지 보여주기
image = imread("recv.jpg");
if (image.empty()) { continue; }
else imshow("recv", image);
// esc 누르면 종료
if (waitKey(33) > 0) break;
}
}
// client fuction
void client_send(SOCKET *sock) {
FILE *fp = NULL;
Mat image;
VideoCapture cap(0);
char buf[BUFSIZE];
while (1) {
// 카메라 접근 후 파일로 작성
cap.read(image);
resize(image, image, Size(300, 400));
imwrite("tmp.jpg", image);
// 파일 열어서 읽고 전송
ZeroMemory(buf, NULL);
fopen_s(&fp, "tmp.jpg", "rb");
fread(buf, BUFSIZE, 1, fp);
send(*sock, buf, sizeof(buf), 0);
fclose(fp);
}
}
4. 결과
5. 추가 기능
- 양방향 영상 송수신, IOCP, P2P, 코덱
728x90
반응형
'Computer Science > Open Source' 카테고리의 다른 글
[Open Source] ChatGPT (1) | 2022.12.04 |
---|---|
FFMPEG 관련 자료 (0) | 2020.12.25 |
[리눅스] Ubuntu 18.04 LTS에서 Tensorflow-GPU 사용하기 (0) | 2018.12.15 |
[윈도우] Visual Studio 2017에서 OpenCV 사용하기 (0) | 2017.10.11 |
[리눅스] Ubuntu16.04 LTS에서 텐서플로우 사용하기 (0) | 2017.10.07 |
[윈도우] Visual Studio 2017에서 텐서플로우 사용하기(2) (0) | 2017.10.07 |
댓글