C++网络编程
1103 浏览 6 years, 2 months
2.1 因特网服务器1
版权声明: 转载请注明出处 http://www.codingsoho.com/实例1: 因特网服务器
SocketAPI就不做介绍了,这个不是本课程的重点
先实现一个简单的服务器,它监听数据,显示结果并退出。
包含文件
#ifdef WIN32 // windows 95 and above
#include "winsock2.h"
#include "Ws2tcpip.h"
#else // UNIX/Linux
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#endif
// End Code Block 2.1 - Header Includes
根据判断预处理红WIN32是否定义,告知它是在WINDOW操作系统还是在Unix/Linux机器上运行。根据不同的操作系统,包含不同的头文件
平台兼容定义
// Code Block 2.2 - Redefinitions and globals For Cross-Compatibility
#ifdef WIN32 // windows 95 and above
WSADATA g_wsadata; // winsock data holder
#define CloseSocket closesocket
#define GetSocketError WSAGetLastError
#define StartSocketLib WSAStartup( MAKEWORD( 2, 2 ), &g_wsadata );
#define CloseSocketLib WSACleanup();
#ifndef socklen_t
typedef int socklen_t;
#endif
#else // Unix/Linux
#define CloseSocket close
#define GetSocketError errno
#define StartSocketLib {}
#define CloseSocketLib {}
#endif
// End Code Block 2.2 - Redefinitions and globals For Cross-Compatibility
Socket API和Winsock library在某些方面有差异,所以需要统一调用接口,让他们在应用调用处没有相同。 上面的接口中,将函数名进行了统一,代码逻辑实现时可以用这个封装过的接口,而不需要特别关心是windows还是linux系统。
C++标准iostream库
#include <iostream> // load the iostream library
using namespace std; // use the std namespace
其他代码
#include <memory.h>
int main()
{
int err; // for getting errors
// start the socket library
StartSocketLib;
// BEGIN CODE BLOCK 2.3 - Create a Listening Socket on port 4000
// create a socket
int sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
// check if socket was created
if( sock == -1 )
{
cout << "Socket creation error!" << endl;
return 0;
}
cout << "Socket created!" << endl;
// create a sockaddr_in for binding, listening on port 4000
struct sockaddr_in socketaddress;
socklen_t sa_size = sizeof( struct sockaddr_in );
socketaddress.sin_family = AF_INET;
socketaddress.sin_port = htons( 4000 );
socketaddress.sin_addr.s_addr = htonl( INADDR_ANY );
memset( &(socketaddress.sin_zero), 0, 8 );
// bind the socket
err = bind( sock, (struct sockaddr*)&socketaddress, sa_size );
if( err == -1 )
{
cout << "Socket binding error!" << endl;
return 0;
}
cout << "Socket bound!" << endl;
// listen on the socket
err = listen( sock, 16 );
if( err == -1 )
{
cout << "Socket listening error!" << endl;
return 0;
}
cout << "Socket listening, waiting for connection..." << endl;
// END CODE BLOCK 2.3 - Create a Listening Socket on port 4000
// wait for an incomming connection now
int datasock;
datasock = accept( sock, (struct sockaddr*)&socketaddress, &sa_size );
if( datasock == -1 )
{
cout << "Socket accepting error!" << endl;
return 0;
}
cout << "Socket accepted, waiting for data..." << endl;
// receive data
char buffer[128];
err = recv( datasock, buffer, 128, 0 );
if( err == -1 )
{
cout << "Socket receiving error!" << endl;
return 0;
}
cout << "Data received:" << endl;
cout << buffer << endl;
shutdown( datasock, 2 );
CloseSocket( datasock );
shutdown( sock, 2 );
CloseSocket( sock );
CloseSocketLib;
}
上面的代码中包括以下功能
- 错误报告
int err;
,每一步操作都可能出错,该变量用于纯粹错误值。 - 创建套接字 -
int sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
,生成套接字sock
- 绑定套接字 -
bind( sock, (struct sockaddr*)&socketaddress, sa_size );
- 监听套接字 -
listen( sock, 16 );
- 等待套接字 -
datasock = accept( sock, (struct sockaddr*)&socketaddress, &sa_size );
,当收到连接时,创建一个新的套接字datasock
- 接收套接字 -
recv( datasock, buffer, 128, 0 );
- 关闭套接字 - 接收完成后,关闭套接字和停止系统
shutdown( datasock, 2 ); CloseSocket( datasock ); shutdown( sock, 2 ); CloseSocket( sock );
程序在编译时碰到错误 > undefined-reference-to-imp-wsacleanup
参考 https://stackoverflow.com/questions/18559028/undefined-reference-to-imp-wsacleanup 解决该问题
In DevC++, navigate to Project >> Project Options (or via usually ctrl+h); then in the "Parameters" tab there is a button "Add Library or Object" and then add libws2_32.a.
本例路径为 > "D:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib/libws2_32.a"