[转] C++ socket 例子

本文介绍了一个使用Winsock进行网络通信的C++控制台程序。该程序实现了一个基本的TCP服务器,能够监听特定端口,接收客户端连接,并与之进行简单的数据交换。文中详细展示了如何通过Winsock库初始化网络环境、创建套接字、绑定端口、监听连接请求及接受客户端连接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

// CSocketSev.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <winsock.h>
#include <iostream>
#pragma comment(lib,"Ws2_32.lib")
#define DEFULT_PORT 2000
SOCKET m_Listening;

int Receive(SOCKET fd , char* szText , int len)
{
int cnt, rc;
cnt = len;
while(cnt > 0)
{
 rc = recv(fd,szText,cnt,0);
 if(rc == SOCKET_ERROR)
 {
 return -1;
 }
 if(rc == 0)
 {
 return len-cnt;
 }
 szText += rc;
 cnt -= rc;
}
return len;
}

int Send(SOCKET fd , char* szText , int len)
{
int cnt , rc;
cnt = len;
while(cnt > 0)
{
 rc = send(fd,szText,cnt,0);
 if(rc == SOCKET_ERROR)
 {
 return -1;
 }
 if(rc == 0)
 {
 return len-cnt;
 }
 szText += rc;
    cnt -= rc;
}
return len;
}

DWORD WINAPI ListenThread(LPVOID Ipparam)
{
 SOCKET Listening = m_Listening;
 //开始监听
 if(listen(Listening,40) == SOCKET_ERROR)
 {
 return -1;
 }
 char szBuf[MAX_PATH];
 memset(szBuf,0,MAX_PATH);
 
 while(1)
 {
  SOCKET ConnectSocket;
  SOCKADDR_IN ClientAddr;
  int         nLen = sizeof(sockaddr);
  //阻塞 线程 直到 有客户端连接 节省资源
  ConnectSocket = accept(Listening,(sockaddr*)&ClientAddr,&nLen);

  char* pAddrname = inet_ntoa(ClientAddr.sin_addr); //将网络地址 转换成 “.” 点隔字符串

  Receive(ConnectSocket,szBuf,100);
//界面显示请求数据
  strcat(szBuf,"来自(");
  strcat(szBuf,pAddrname);
  strcat(szBuf,")");

  Send(ConnectSocket,szBuf,100);
  puts(szBuf);

 }
 return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
 WSADATA wsaData;
 if(WSAStartup(0x0110,&wsaData)) //调用 windowSocketDll
 {
 puts("Winsock无法初始化");
   
 return -1;
 }
 DWORD dwThreadID = 0;

 sockaddr_in local;

 local.sin_family = AF_INET;
    
 //设置端口 DEFAULT_PORT
 if(argc > 0)
 {
  local.sin_port = htons((u_short)argv[0]); //htons 将主机的无符号短整形数 转换成网络字节顺序
 }
 else
 {
  local.sin_port = htons(DEFULT_PORT);
 }
 //ip 设置成 INADDR_ANY 系统自动查找
 local.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//INADDR_ANY;

 //初始化Socket
 m_Listening = socket(AF_INET,SOCK_STREAM,0);

 if(m_Listening == INVALID_SOCKET)
 {
  puts("创建Winsock实例失败!");
  return -1;
 }
 if(bind(m_Listening,(sockaddr*)&local.sin_addr,sizeof(local) == SOCKET_ERROR))
 {
 closesocket(m_Listening);
 puts("绑定端口失败");
 return -1;
 }
 if(m_Listening == SOCKET_ERROR)
 {
  puts("监听端口失败");
  return -1;
 }
 puts("启动成功");

 char szBuf[MAX_PATH];
 //初始化
 memset(szBuf,0,MAX_PATH);

 while(1)
 {
  SOCKET ConnectSocket;

  sockaddr_in ClientAddr;

  int         nLen = sizeof(sockaddr);

  //阻塞
  ConnectSocket = accept(m_Listening,(sockaddr*)&ClientAddr,&nLen);

  //得到客户端IP
  char* pAddrname = inet_ntoa(ClientAddr.sin_addr);

  Receive(ConnectSocket,szBuf,100);

  //像客户端 发送回复
  Send(ConnectSocket,szBuf,100);

  //界面显示数据
  strcat(szBuf,"来自(");
  strcat(szBuf,pAddrname);
  strcat(szBuf,")");

  puts(szBuf);
 }
 
 //return 0;
}

 

C++中实现Socket通信通常涉及使用Berkeley套接字(也称为BSD套接字)API,这些API在大多数操作系统中都可用,包括Windows和Linux。下面是一个简单的TCP服务器和客户端的实现示例。 ### TCP服务器示例 TCP服务器通常执行以下步骤: 1. 创建套接字。 2. 绑定到一个地址和端口。 3. 监听连接。 4. 接受连接。 5. 发送和接收数据。 6. 关闭连接。 ```cpp #include <iostream> #include <winsock2.h> // Windows平台需要包含这个头文件 #include <ws2tcpip.h> #pragma comment(lib, "ws2_32.lib") // 链接ws2_32库 int main() { WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { std::cerr << "WSAStartup failed: " << iResult << std::endl; return 1; } struct addrinfo *result = NULL, hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; // Resolve the server address and port iResult = getaddrinfo(NULL, "27015", &hints, &result); if (iResult != 0) { std::cerr << "getaddrinfo failed: " << iResult << std::endl; WSACleanup(); return 1; } // Create a SOCKET for connecting to server SOCKET ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ListenSocket == INVALID_SOCKET) { std::cerr << "Error at socket(): " << WSAGetLastError() << std::endl; freeaddrinfo(result); WSACleanup(); return 1; } // Setup the TCP listening socket iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); if (iResult == SOCKET_ERROR) { std::cerr << "bind failed with error: " << WSAGetLastError() << std::endl; freeaddrinfo(result); closesocket(ListenSocket); WSACleanup(); return 1; } freeaddrinfo(result); if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) { std::cerr << "Listen failed with error: " << WSAGetLastError() << std::endl; closesocket(ListenSocket); WSACleanup(); return 1; } SOCKET ClientSocket = accept(ListenSocket, NULL, NULL); if (ClientSocket == INVALID_SOCKET) { std::cerr << "accept failed: " << WSAGetLastError() << std::endl; closesocket(ListenSocket); WSACleanup(); return 1; } // No longer need server socket closesocket(ListenSocket); // Receive until the peer shuts down the connection char recvbuf[512]; int recvbuflen = 512; do { iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); if (iResult > 0) std::cout << "Bytes received: " << iResult << std::endl; else if (iResult == 0) std::cout << "Connection closed" << std::endl; else std::cerr << "recv failed: " << WSAGetLastError() << std::endl; } while (iResult > 0); // shutdown the connection since no more data will be sent if (shutdown(ClientSocket, SD_SEND) == SOCKET_ERROR) { std::cerr << "shutdown failed: " << WSAGetLastError() << std::endl; } // cleanup closesocket(ClientSocket); WSACleanup(); return 0; } ``` ### TCP客户端示例 TCP客户端通常执行以下步骤: 1. 创建套接字。 2. 连接到服务器。 3. 发送和接收数据。 4. 关闭连接。 ```cpp #include <iostream> #include <winsock2.h> #include <ws2tcpip.h> #pragma comment(lib, "ws2_32.lib") int main() { WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { std::cerr << "WSAStartup failed: " << iResult << std::endl; return 1; } struct addrinfo *result = NULL, hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; // Resolve the server address and port iResult = getaddrinfo("127.0.0.1", "27015", &hints, &result); if (iResult != 0) { std::cerr << "getaddrinfo failed: " << iResult << std::endl; WSACleanup(); return 1; } // Attempt to connect to an address until one succeeds for (struct addrinfo *ptr = result; ptr != NULL; ptr = ptr->ai_next) { // Create a SOCKET for connecting to server SOCKET ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { std::cerr << "Error at socket(): " << WSAGetLastError() << std::endl; WSACleanup(); return 1; } // Connect to server. iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); if (iResult == SOCKET_ERROR) { closesocket(ConnectSocket); ConnectSocket = INVALID_SOCKET; continue; } break; } freeaddrinfo(result); if (ConnectSocket == INVALID_SOCKET) { std::cerr << "Unable to connect to server!" << std::endl; WSACleanup(); return 1; } // Send an initial buffer const char *sendbuf = "this is a test"; iResult = send(ConnectSocket, sendbuf, strlen(sendbuf), 0); // 使用send函数发送数据[^1] if (iResult == SOCKET_ERROR) { std::cerr << "send failed: " << WSAGetLastError() << std::endl; closesocket(ConnectSocket); WSACleanup(); return 1; } std::cout << "Bytes Sent: " << iResult << std::endl; // shutdown the connection since no more data will be sent iResult = shutdown(ConnectSocket, SD_SEND); if (iResult == SOCKET_ERROR) { std::cerr << "shutdown failed: " << WSAGetLastError() << std::endl; } // cleanup closesocket(ConnectSocket); WSACleanup(); return 0; } ``` 这些示例展示了如何在Windows平台上使用Winsock API来创建一个简单的TCP服务器和客户端。对于Linux平台,代码大致相同,但不需要包含`winsock2.h`和`ws2tcpip.h`,而是使用`sys/socket.h`、`netinet/in.h`、`arpa/inet.h`等头文件,并且链接不同的库。此外,在Linux上编译时不需要调用`WSAStartup`和`WSACleanup`函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值