- 实验目的
1. 学习网络进程间通信
2. 深刻理解Client/Server模型
3. 熟练掌握Socket编程接口(API)
3.1 基于UDP协议通信编程(单向,双向,视频文件传输)
3.2 基于TCP协议通信编程(单向,双向,视频文件传输)
2、实验要求
UDP :
n 单向通信:客户端将从键盘输入任意字符串发送给服 务器,服务器接收到后将该字符串在屏幕上打印,并 将客户端IP地址和PORT打印;
n 双向通信:( 1)客户端将从键盘输入任意字符串发送 给服务器,服务器接收到后将该字符串在屏幕上打印, 并将客户端IP地址和PORT打印;( 2)服务器将客户 端发送来字符串的服务器发送给客户端,客户端打印 字符串和服务器IP地址和PORT;
n 传输多媒体文件:客户端将一个视频文件发送给服务 器,在服务器上是否能播放;在发送过程中将“网络 接口 -停止”( 3 到 6秒),检测可否正常传输文件。
TCP:
问题1:基于TCP协议通信中,客户端何时知道通信五元组。
SOCKET socket( int af, int type, int protocol );
int connect(SOCKET socketid, const struct sockaddr FAR *seradd, int seraddlen )
问题2:基于TCP协议通信中,客户端何时知道通信五元组。
SOCKET socket( int af, int type, int protocol );
int bind( SOCKET socketid, const struct sockaddr FAR * seradd, int seraddlen )
LISTEN();
SOCKET accept( SOCKET s, struct sockaddr FAR * cliaddr,int FAR * cliaddrlen )
结论:服务器只要调用了accept,才知道五元组;连接建立好以后,CLIENT与SERVER谁先发送TCP数据段都可以。
、相关技术及知识
1. 网络间进程通信
2. Client/Server模式
网络中进程间通信模式:客户/ 服务(C/S:Client/Server)模式。
客户向服务器主动发出服务请求,服务器等待接收服务请求,并根据自身的资源状态进行应答与服务。
TCP协议:客户进程首先主动向服务器进程发送连接请求,通过三次握手,建立连接,实际上是获得五元组(连接表);通信时任意一方可以向对方发送数据;通信结束后,任一方可通过四次握手释放连接。
UDP协议:客户进程必须首先主动向服务器进程发送服务请求(数据),这时服务器才得到通信五元组信息;此后,服务器才可以向客户进程发送应答。
3. Socket编程接口
- 为了便于网络进程间使用TCP/UDP进行通信,传输层向应用层提供了一套编程接口—套接字(Socket)编程接口。
- 套接字编程接口包括以下主要API:
- 创建socket:socket( )
- 绑定本地地址:bind( ) – 主要用于服务器端
- 建立socket连接:connect( )
- 接收连接请求:listen( ) 、accept( )
- 发送数据:send( ) , sendto( )
- 接收数据:recv( ) , recvfrom( )
5、程序代码
代码及可执行程序见附件.
UDP:
2 双向通信:1_2
// udp_client.cpp
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <iostream>
#include <string>
#include <stdio.h>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int main()
{
int iResult = 0;
WSADATA wsaData;
SOCKET SendSocket;
struct sockaddr_in RecvAddr;
int RecvAddrSize = sizeof (RecvAddr);
unsigned short Port = 6666;
struct sockaddr_in SendAddr;
int SendAddrSize = sizeof (SendAddr);
//-----------------------------------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error %d\n", iResult);
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (SendSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
wprintf(L"Sending datagrams...\n");
std::string str;
std::cout << "Please input your message: ";
std::cin >> str;
iResult = sendto(SendSocket, str.c_str(), str.length(), 0, (SOCKADDR *) &RecvAddr, RecvAddrSize);
if (iResult == SOCKET_ERROR) {
wprintf(L"sen failed with error %d\n", WSAGetLastError());
}
wprintf(L"Finished sending.\n");
char RecvBuf[1024] = {0}; // 接收数据的buffer
int BufLen = 1024; // buffer 长度
iResult = recvfrom(SendSocket,
RecvBuf, BufLen, 0, (SOCKADDR *)&SendAddr, &SendAddrSize);
wprintf(L"Finished receiving from %s:%u. Closing socket.\n", inet_ntoa(SendAddr.sin_addr), SendAddr.sin_port);
printf("Message: %s\n", RecvBuf);
//-----------------------------------------------
// Close the socket when finished receiving datagrams
iResult = closesocket(SendSocket);
if (iResult == SOCKET_ERROR) {
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Clean up and exit.
wprintf(L"Exiting.\n");
WSACleanup();
return 0;
}
//udp_server.cpp
//#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <WS2tcpip.h>
#include <Ws2tcpip.h>
#include <stdio.h>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
int main()
{
int iResult = 0;
WSADATA wsaData;
SOCKET RecvSocket; //服务端用于接收客户端书局的套接字
struct sockaddr_in RecvAddr; //服务端监听的地址
unsigned short Port = 6666; //服务端监听的端口
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
//-----------------------------------------------
// 初始化 Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
wprintf(L"WSAStartup failed with error %d\n", iResult);
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
// 创建服务端接收数据的套接字
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (RecvSocket == INVALID_SOCKET)
{
wprintf(L"socket failed with error %d\n", WSAGetLastError());
return 1;
}
//绑定0.0.0.0:6666
iResult = bind(RecvSocket, (SOCKADDR *)&RecvAddr, sizeof(RecvAddr));
if (iResult != 0)
{
wprintf(L"bind failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
wprintf(L"Receiving datagrams...\n");
char RecvBuf[1024] = {0}; // 接收数据的buffer
int BufLen = 1024; // buffer 长度
struct sockaddr_in SendAddr; // recvfrom的传入参数, recvfrom成功后为发送者的地址
int SendAddrSize = sizeof(SendAddr);
iResult = recvfrom(RecvSocket,
RecvBuf, BufLen, 0, (SOCKADDR *)&SendAddr, &SendAddrSize);
if (iResult == SOCKET_ERROR)
{
wprintf(L"recvfrom failed with error %d\n", WSAGetLastError());
}
//-----------------------------------------------
wprintf(L"Finished receiving from %s:%u. Sending back.\n", inet_ntoa(SendAddr.sin_addr), SendAddr.sin_port);
printf("Message: %s\n", RecvBuf);
// 将接收的数据包发回去
iResult = sendto(RecvSocket, RecvBuf, strlen(RecvBuf), 0, (SOCKADDR *)&SendAddr, SendAddrSize);
wprintf(L"Finished send to %s:%u. Closing socket.\n", inet_ntoa(SendAddr.sin_addr), SendAddr.sin_port);
//
iResult = closesocket(RecvSocket);
if (iResult == SOCKET_ERROR)
{
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Clean up and exit.
wprintf(L"Exiting.\n");
WSACleanup();
return 0;
}
3 文件传输:1_3
//udp_client.cpp
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <cstring>
#include <fstream>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
int main()
{
int iResult = 0;
WSADATA wsaData;
SOCKET SendSocket;
struct sockaddr_in RecvAddr;
int RecvAddrSize = sizeof(RecvAddr);
unsigned short Port = 6666;
struct sockaddr_in SendAddr;
int SendAddrSize = sizeof(SendAddr);
//-----------------------------------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
wprintf(L"WSAStartup failed with error %d\n", iResult);
return 1;
}
//-----------------------------------------------
// Create a send socket to receive datagrams
SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (SendSocket == INVALID_SOCKET)
{
wprintf(L"socket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
wprintf(L"Sending datagrams...\n");
// std::string str;
// std::cout << "Please input your message: ";
// std::cin >> str;
// iResult = sendto(SendSocket, str.c_str(), str.length(), 0, (SOCKADDR *)&RecvAddr, RecvAddrSize);
int haveSend = 0;
const int bufferSize = 1024;
char buffer[bufferSize] = {0};
int readLen = 0;
string srcFileName = "1111.avi";
ifstream srcFile;
srcFile.open(srcFileName.c_str(), ios::binary);
if (!srcFile)
{
return 1;
}
int ir;
while (!srcFile.eof())
{
srcFile.read(buffer, bufferSize);
readLen = srcFile.gcount();
// cout <<"readlen:" <<readLen<<endl;
iResult=sendto(SendSocket, buffer, readLen, 0,(SOCKADDR *)&RecvAddr, RecvAddrSize);
haveSend += readLen;
cout <<"send accesss! Havesend:" << haveSend<<endl;
Sleep(0.01);
}
srcFile.close();
cout << "send: " << haveSend << "B" << endl;
if (iResult == SOCKET_ERROR)
{
wprintf(L"sen failed with error %d\n", WSAGetLastError());
}
wprintf(L"Finished sending.\n");
// char RecvBuf[1024] = {0}; // 接收数据的buffer
// int BufLen = 1024; // buffer 长度
// iResult = recvfrom(SendSocket,
// RecvBuf, BufLen, 0, (SOCKADDR *)&SendAddr, &SendAddrSize);
// wprintf(L"Finished receiving from %s:%u. Closing socket.\n", inet_ntoa(SendAddr.sin_addr), SendAddr.sin_port);
// printf("Message: %s\n", RecvBuf);
//-----------------------------------------------
// Close the socket when finished receiving datagrams
iResult = closesocket(SendSocket);
if (iResult == SOCKET_ERROR)
{
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Clean up and exit.
wprintf(L"Exiting.\n");
WSACleanup();
return 0;
}
//udp_server.cpp
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <WS2tcpip.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int main()
{
int iResult = 0;
WSADATA wsaData;
SOCKET RecvSocket; //服务端用于接收客户端书局的套接字
struct sockaddr_in RecvAddr; //服务端监听的地址
unsigned short Port = 6666; //服务端监听的端口
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
//-----------------------------------------------
// 初始化 Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
wprintf(L"WSAStartup failed with error %d\n", iResult);
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
// 创建服务端接收数据的套接字
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (RecvSocket == INVALID_SOCKET)
{
wprintf(L"socket failed with error %d\n", WSAGetLastError());
return 1;
}
//绑定0.0.0.0:6666
iResult = bind(RecvSocket, (SOCKADDR *)&RecvAddr, sizeof(RecvAddr));
if (iResult != 0)
{
wprintf(L"bind failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
wprintf(L"Receiving datagrams...\n");
// char RecvBuf[1024] = {0}; // 接收数据的buffer
// int BufLen = 1024; // buffer 长度
struct sockaddr_in SendAddr; // recvfrom的传入参数, recvfrom成功后为发送者的地址
int SendAddrSize = sizeof(SendAddr);
// iResult = recvfrom(RecvSocket,
// RecvBuf, BufLen, 0, (SOCKADDR *)&SendAddr, &SendAddrSize);
// if (iResult == SOCKET_ERROR)
// {
// wprintf(L"recvfrom failed with error %d\n", WSAGetLastError());
// }
// //-----------------------------------------------
// wprintf(L"Finished receiving from %s:%u. Sending back.\n", inet_ntoa(SendAddr.sin_addr), SendAddr.sin_port);
// printf("Message: %s\n", RecvBuf);
// // 将接收的数据包发回去
// iResult = sendto(RecvSocket, RecvBuf, strlen(RecvBuf), 0, (SOCKADDR *)&SendAddr, SendAddrSize);
// wprintf(L"Finished send to %s:%u. Closing socket.\n", inet_ntoa(SendAddr.sin_addr), SendAddr.sin_port);
cout << "start recv!" << endl;
int bufferSize = 1024;
char buffer[1024] = {0};
int readLen = 0;
string desFileName = "received.avi";
ofstream desFile;
desFile.open(desFileName.c_str(), ios::binary);
if (!desFile)
{
cout << "open failed!" << endl;
return 1;
}
int sumlen = 0;
do
{
readLen = recvfrom(RecvSocket, buffer, bufferSize, 0, (SOCKADDR *)&SendAddr, &SendAddrSize);
if (readLen == SOCKET_ERROR)
{
cout << "receive failed!" << endl;
break;
}
else
{
desFile.write(buffer, bufferSize);
sumlen += bufferSize;
cout << "file write success!" << sumlen << endl;
if (sumlen > 3838464)
break;
}
} while (true);
desFile.close();
cout << " recv finish!" << endl; //
iResult = closesocket(RecvSocket);
if (iResult == SOCKET_ERROR)
{
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Clean up and exit.
wprintf(L"Exiting.\n");
WSACleanup();
return 0;
}
TCP:
2 双向通信:2_2
//client.cpp
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <iostream>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
int main()
{
int iResult = 0;
WSADATA wsaData;
SOCKET SendSocket;
struct sockaddr_in RecvAddr;
int RecvAddrSize = sizeof(RecvAddr);
unsigned short Port = 6666;
struct sockaddr_in SendAddr;
int SendAddrSize = sizeof(SendAddr);
//-----------------------------------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
wprintf(L"WSAStartup failed with error %d\n", iResult);
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
SendSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (SendSocket == INVALID_SOCKET)
{
wprintf(L"socket failed with error %d\n", WSAGetLastError());
return 1;
}
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(SendSocket, (SOCKADDR *)&RecvAddr, RecvAddrSize) == INVALID_SOCKET)
{
cout << "connect() failed: " << WSAGetLastError() << endl;
return 1;
}
//-----------------------------------------------
std::string str;
std::cout << "Please input your message: ";
std::cin >> str;
iResult = send(SendSocket, str.c_str(), str.length(), 0);
if (iResult == SOCKET_ERROR)
{
wprintf(L"sen failed with error %d\n", WSAGetLastError());
}
wprintf(L"Finished sending.\n");
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
char RecvBuf[1024] = {0}; // 接收数据的buffer
int BufLen = 1024; // buffer 长度
iResult = recv(SendSocket, RecvBuf, BufLen, 0);
if (iResult == SOCKET_ERROR)
{
cout << "rcv() failed:" << WSAGetLastError() << endl;
return 1;
}
wprintf(L"Finished receiving from %s:%u. Closing socket.\n", inet_ntoa(RecvAddr.sin_addr), RecvAddr.sin_port);
printf("Message: %s\n", RecvBuf);
//-----------------------------------------------
// Close the socket when finished receiving datagrams
iResult = closesocket(SendSocket);
if (iResult == SOCKET_ERROR)
{
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Clean up and exit.
wprintf(L"Exiting.\n");
WSACleanup();
return 0;
}
//server.cpp
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <WS2tcpip.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#include <iostream>
using namespace std;
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int main()
{
int iResult = 0;
WSADATA wsaData;
SOCKET RecvSocket; //服务端用于接收客户端书局的套接字
struct sockaddr_in RecvAddr; //服务端监听的地址
unsigned short Port = 6666; //服务端监听的端口
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
//-----------------------------------------------
// 初始化 Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
wprintf(L"WSAStartup failed with error %d\n", iResult);
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
// 创建服务端接收数据的套接字
RecvSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (RecvSocket == INVALID_SOCKET)
{
wprintf(L"socket failed with error %d\n", WSAGetLastError());
return 1;
}
//绑定0.0.0.0:6666
iResult = bind(RecvSocket, (SOCKADDR *)&RecvAddr, sizeof(RecvAddr));
if (iResult != 0)
{
wprintf(L"bind failed with error %d\n", WSAGetLastError());
return 1;
}
iResult = listen(RecvSocket, 5);
if (iResult == SOCKET_ERROR)
{
cout << "listen() failed:" << WSAGetLastError() << endl;
return 1;
}
wprintf(L"Receiving datagrams...\n");
char RecvBuf[1024] = {0}; // 接收数据的buffer
int BufLen = 1024; // buffer 长度
struct sockaddr_in SendAddr; // recvfrom的传入参数, recvfrom成功后为发送者的地址
int SendAddrSize = sizeof(SendAddr);
SOCKET newSocket = accept(RecvSocket, (SOCKADDR *)&SendAddr, &SendAddrSize);
if (newSocket == INVALID_SOCKET)
{
cout << "accept() failed:" << WSAGetLastError() << endl; //
return 1;
}
iResult = recv(newSocket, RecvBuf, BufLen, 0);
if (iResult == SOCKET_ERROR)
{
cout << "rcv() failed:" << WSAGetLastError() << endl;
return 1;
}
if (iResult == 0)
{
cout << "no receive message!" << endl;
}
else
{
cout << "received success, message :" << RecvBuf << endl;
cout << "ip:port:" << inet_ntoa(SendAddr.sin_addr) << SendAddr.sin_port << endl;
}
iResult = send(newSocket, RecvBuf, BufLen, 0);
if (iResult == SOCKET_ERROR)
{
cout << "send() failed:" << WSAGetLastError() << endl;
return 1;
}
if (iResult == 0)
{
cout << "no send message!" << endl;
}
else
{
cout << "send success, message: " << RecvBuf << endl;
}
//-----------------------------------------------
// wprintf(L"Finished receiving from %s:%u. Sending back.\n", inet_ntoa(SendAddr.sin_addr), SendAddr.sin_port);
// printf("Message: %s\n", RecvBuf);
// // 将接收的数据包发回去
// iResult = sendto(RecvSocket, RecvBuf, strlen(RecvBuf), 0, (SOCKADDR *)&SendAddr, SendAddrSize);
// wprintf(L"Finished send to %s:%u. Closing socket.\n", inet_ntoa(SendAddr.sin_addr), SendAddr.sin_port);
// //
iResult = closesocket(RecvSocket);
if (iResult == SOCKET_ERROR)
{
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
return 1;
}
WSACleanup();
closesocket(newSocket);
wprintf(L"Exiting.\n");
return 0;
}
3 文件传输:2_3
//client.cpp
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <iostream>
#include <fstream>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
int main()
{
int iResult = 0;
WSADATA wsaData;
SOCKET SendSocket;
struct sockaddr_in RecvAddr;
int RecvAddrSize = sizeof(RecvAddr);
unsigned short Port = 6666;
struct sockaddr_in SendAddr;
int SendAddrSize = sizeof(SendAddr);
//-----------------------------------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
wprintf(L"WSAStartup failed with error %d\n", iResult);
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
SendSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (SendSocket == INVALID_SOCKET)
{
wprintf(L"socket failed with error %d\n", WSAGetLastError());
return 1;
}
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(SendSocket, (SOCKADDR *)&RecvAddr, RecvAddrSize) == INVALID_SOCKET)
{
cout << "connect() failed: " << WSAGetLastError() << endl;
return 1;
}
//-----------------------------------------------
int haveSend = 0;
const int bufferSize = 1024;
char buffer[bufferSize] = {0};
int readLen = 0;
string srcFileName = "1111.avi";
ifstream srcFile;
srcFile.open(srcFileName.c_str(), ios::binary);
if (!srcFile)
{
return 1;
}
while (!srcFile.eof())
{
srcFile.read(buffer, bufferSize);
readLen = srcFile.gcount();
send(SendSocket, buffer, readLen, 0);
haveSend += readLen;
cout << "send accesss! Havesend:" << haveSend << endl;
Sleep(0.01);
}
srcFile.close();
cout << "send: " << haveSend << "B" << endl;
//
// iResult = send(SendSocket, str.c_str(), str.length(), 0);
// if (iResult == SOCKET_ERROR)
// {
// wprintf(L"sen failed with error %d\n", WSAGetLastError());
// }
// wprintf(L"Finished sending.\n");
// //-----------------------------------------------
// // Call the recvfrom function to receive datagrams
// // on the bound socket.
// char RecvBuf[1024] = {0}; // 接收数据的buffer
// int BufLen = 1024; // buffer 长度
// iResult = recv(SendSocket, RecvBuf, BufLen, 0);
// if (iResult == SOCKET_ERROR)
// {
// cout << "rcv() failed:" << WSAGetLastError() << endl;
// return 1;
// }
// wprintf(L"Finished receiving from %s:%u. Closing socket.\n", inet_ntoa(RecvAddr.sin_addr), RecvAddr.sin_port);
// printf("Message: %s\n", RecvBuf);
//-----------------------------------------------
// Close the socket when finished receiving datagrams
iResult = closesocket(SendSocket);
if (iResult == SOCKET_ERROR)
{
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Clean up and exit.
wprintf(L"Exiting.\n");
WSACleanup();
return 0;
}
//server.cpp
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <WS2tcpip.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int main()
{
int iResult = 0;
WSADATA wsaData;
SOCKET RecvSocket; //服务端用于接收客户端书局的套接字
struct sockaddr_in RecvAddr; //服务端监听的地址
unsigned short Port = 6666; //服务端监听的端口
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
//-----------------------------------------------
// 初始化 Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
wprintf(L"WSAStartup failed with error %d\n", iResult);
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
// 创建服务端接收数据的套接字
RecvSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (RecvSocket == INVALID_SOCKET)
{
wprintf(L"socket failed with error %d\n", WSAGetLastError());
return 1;
}
//绑定0.0.0.0:6666
iResult = bind(RecvSocket, (SOCKADDR *)&RecvAddr, sizeof(RecvAddr));
if (iResult != 0)
{
wprintf(L"bind failed with error %d\n", WSAGetLastError());
return 1;
}
iResult = listen(RecvSocket, 5);
if (iResult == SOCKET_ERROR)
{
cout << "listen() failed:" << WSAGetLastError() << endl;
return 1;
}
wprintf(L"Receiving datagrams...\n");
char RecvBuf[1024] = {0}; // 接收数据的buffer
int BufLen = 1024; // buffer 长度
struct sockaddr_in SendAddr; // recvfrom的传入参数, recvfrom成功后为发送者的地址
int SendAddrSize = sizeof(SendAddr);
SOCKET newSocket = accept(RecvSocket, (SOCKADDR *)&SendAddr, &SendAddrSize);
if (newSocket == INVALID_SOCKET)
{
cout << "accept() failed:" << WSAGetLastError() << endl; //
return 1;
}
cout << "start recv!" << endl;
const int bufferSize = 1024;
char buffer[bufferSize] = {0};
int readLen = 0;
string desFileName = "receive.avi";
ofstream desFile;
desFile.open(desFileName.c_str(), ios::binary);
if (!desFile)
{
return 1;
}
int sumlen = 0;
do
{
readLen = recv(newSocket, buffer, bufferSize, 0);
if (readLen == 0)
{
cout << "receive failed!" << endl;
break;
}
else
{
desFile.write(buffer, readLen);
sumlen += bufferSize;
cout << "file write success!" << sumlen << endl;
if (sumlen > 3838464)
break;
}
} while (true);
desFile.close();
//
// iResult = recv(newSocket, RecvBuf, BufLen, 0);
// if (iResult == SOCKET_ERROR)
// {
// cout << "rcv() failed:" << WSAGetLastError() << endl;
// return 1;
// }
// if (iResult == 0)
// {
// cout << "no receive message!" << endl;
// }
// else
// {
// cout << "received success, message :" << RecvBuf << endl;
// cout << "ip:port:" << inet_ntoa(SendAddr.sin_addr) << SendAddr.sin_port << endl;
// }
// iResult = send(newSocket, RecvBuf, BufLen, 0);
// if (iResult == SOCKET_ERROR)
// {
// cout << "send() failed:" << WSAGetLastError() << endl;
// return 1;
// }
// if (iResult == 0)
// {
// cout << "no send message!" << endl;
// }
// else
// {
// cout << "send success, message: " << RecvBuf << endl;
// }
//-----------------------------------------------
// wprintf(L"Finished receiving from %s:%u. Sending back.\n", inet_ntoa(SendAddr.sin_addr), SendAddr.sin_port);
// printf("Message: %s\n", RecvBuf);
// // 将接收的数据包发回去
// iResult = sendto(RecvSocket, RecvBuf, strlen(RecvBuf), 0, (SOCKADDR *)&SendAddr, SendAddrSize);
// wprintf(L"Finished send to %s:%u. Closing socket.\n", inet_ntoa(SendAddr.sin_addr), SendAddr.sin_port);
// //
iResult = closesocket(RecvSocket);
if (iResult == SOCKET_ERROR)
{
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
return 1;
}
WSACleanup();
closesocket(newSocket);
wprintf(L"Exiting.\n");
return 0;
}
6、运行结果与分析
UDP:
2 双向通信:1_2
3 文件传输:1_3
TCP:
2 双向通信:2_2
3 文件传输:2_3