流媒体传输协议基于TCP/IP协议实现,所谓协议就是规范,谁是最早的创建者谁就有权利制定协议,网络通讯一般需要IP地址和端口,IP用来定位计算机,端口用来定位应用,固TCP/IP协议为所有网络通讯协议的基础协议,基本上我们所接触的所有的网络通讯协议如:ftp、http、svn、rtsp...等等传输协议,只要包含IP和端口的网络通讯协议都是基于TCP/IP协议之上实现的高级传输协议。高级协议之间存在的差异性往往在于交易报文头和报文体的规范上的差异。
所以,学习流媒体我们需要先掌握C++实现套接字通讯的算法:
服务端:
// SoketServer.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#define MAXBUFLEN 10000
#define PORT 6000
typedef struct {
unsigned short len;
char cnt[MAXBUFLEN];
} Msg;
int _tmain(int argc, _TCHAR* argv[])
{
//创建套接字加载套接字
WSADATA wsaData;
//打开套接字
WSAStartup(MAKEWORD(1, 1), &wsaData);
//服务端需要绑定的参数
SOCKADDR_IN serverAddr;
serverAddr.sin_family = AF_INET;//指定协议簇,AF_INET表示的TCP/IP协议
serverAddr.sin_addr.s_addr = INADDR_ANY;//IP地址,INADDR_ANY|NULL默认取本机IP
serverAddr.sin_port = htons(PORT);//绑定端口
//创建套接字服务端
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//绑定服务端套接字和服务端IP、PORT、协议端口
bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(SOCKADDR));
//启动套接字服务监听器
listen(serverSocket, 1);//其中第二个参数代表能够接收的最多的连接数
printf("正在等待客户端的接入...\n");
while(true) {
SOCKADDR clientAddr;
int len = sizeof(SOCKADDR);
SOCKET clientSocket = accept(serverSocket, &clientAddr, &len);
printf("有新客户已连接进来\n\n");
char* welcome = "欢迎光临";
Msg *wm = (Msg*)malloc(sizeof(Msg));
wm->len = strlen(welcome);
strcpy(wm->cnt, welcome);
char wmBuf[sizeof(Msg)];
memcpy(wmBuf, wm, sizeof(Msg));
send(clientSocket, wmBuf, strlen(wm->cnt) + sizeof(wm->len) + sizeof(char), NULL);
free(wm);
while(true) {
//收消息
Msg *m = (Msg*)malloc(sizeof(Msg));
char receiveBuf[sizeof(Msg)];//申请消息接收缓存
int rev_len = recv(clientSocket, receiveBuf, strlen(receiveBuf), NULL);//接收客户端发送的消息
unsigned short len;
memcpy(&len, receiveBuf, 2);
int revable_len = (int)len + sizeof(m->len) + sizeof(char);
while(rev_len < revable_len) {
char* bufPipe = new char[revable_len - rev_len];
rev_len += recv(clientSocket, bufPipe, strlen(bufPipe), NULL);//如果没接收完毕,继续接收
strcat(receiveBuf, bufPipe);
delete bufPipe;
}
memcpy(m, receiveBuf, sizeof(receiveBuf));
printf("收到客户发来的消息长度(%d):\n%s\n", m->len, m->cnt);
if(rev_len < 3 || !strcmp(m->cnt, "bye")) {
printf("客户已断开连接.\n");
break;
}
free(m);
//发送消息
Msg* _sm = (Msg*)malloc(sizeof(Msg));
char sendBuf[sizeof(Msg)];
printf("回复:");
gets(_sm->cnt);
_sm->len = strlen(_sm->cnt);
memcpy(sendBuf, _sm, sizeof(Msg));
send(clientSocket, sendBuf, strlen(_sm->cnt) + sizeof(_sm->len) + sizeof(char), NULL);//发送消息
printf("共发送内容长度(%d)等待服务器回复...\n", _sm->len);
free(_sm);
}
closesocket(clientSocket);//关闭客户端
};
closesocket(serverSocket);//关闭服务端
WSACleanup();//释放资源操作
system("pause");
return 0;
}
客户端:
// SocketClient.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#define PORT 6000
#define DEST_IP_ADDR "192.168.1.103"
#define MAX_LEN 100000
typedef struct {
unsigned short len;
char cnt[MAX_LEN];
} Msg;
int _tmain(int argc, _TCHAR* argv[])
{
//加载套接字
WSADATA wsaData;
WSAStartup(MAKEWORD(1, 1), &wsaData);
SOCKADDR_IN socketAddr;
socketAddr.sin_addr.s_addr = inet_addr(DEST_IP_ADDR);
socketAddr.sin_family = AF_INET;
socketAddr.sin_port = htons(PORT);
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(clientSocket, (LPSOCKADDR)&socketAddr, sizeof(SOCKADDR));//注意第三个参数
while(true) {
//接收服务端消息
Msg *m = (Msg*)malloc(sizeof(Msg));
char receiveBuf[sizeof(Msg)];//申请消息接收缓存
int rev_len = recv(clientSocket, receiveBuf, strlen(receiveBuf), NULL);//接收客户端发送的消息
unsigned short len;
memcpy(&len, receiveBuf, 2);
int revable_len = (int)len + sizeof(m->len) + sizeof(char);
while(rev_len < revable_len) {
char* bufPipe = new char[revable_len - rev_len];
rev_len += recv(clientSocket, bufPipe, strlen(bufPipe), NULL);//如果没接收完毕,继续接收
strcat(receiveBuf, bufPipe);
delete bufPipe;
}
memcpy(m, receiveBuf, sizeof(receiveBuf));
printf("收到服务器发来的消息长度(%d):\n%s\n", m->len, m->cnt);
//发送消息
Msg* _m = (Msg*)malloc(sizeof(Msg));
char sendBuf[sizeof(Msg)];
printf("回复服务器:");
gets(_m->cnt);
_m->len = strlen(_m->cnt);
memcpy(sendBuf, _m, sizeof(Msg));
send(clientSocket, sendBuf, strlen(_m->cnt) + sizeof(_m->len) + sizeof(char), NULL);
printf("共发送内容长度(%d)等待服务器回复...\n", _m->len);
free(_m);
}
closesocket(clientSocket);
WSACleanup();
system("pause");
return 0;
}