Windows平台Socket通信实例

1. 概述

Windows平台下的Socket通信方式主要采用的有TCP(SOCK_STREAM)通信和UDP通信(SOCK_DGRAM)两种。对于第一种通信方式需要建立可靠的连接且要进行校验;另外一种网络传输方式不需要建立可靠的连接,也不进行校验,使用在语音通信和视频通信中。下面就将对Windows平台下创建TCP通信进行流程的说明和相关解释。
Windows上TCP通信的步骤:
文件发送端:
1. 加载和创建套接字,使用到的函数有WSAStartup()(初始化Windows的相关DLL)和socket()(创建一个套接字绑定到一个特定的传输方式如传输的方式、通信的类型)。
2. 向目标端发送连接请求使用的是connect()函数,函数调用成功返回0;
3. 向目标端发送数据send()函数;
4. 关闭套接字,关闭加载的套接字库closesocket()、WSACleanup()。

文件接收端:
1. 加载和创建套接字,使用到的函数有WSAStartup()(初始化Windows的相关DLL)和socket()(创建一个套接字绑定到一个特定的传输方式如传输的方式、通信的类型)。
2. 绑定套接字到一个IP地址和一个端口上,使用bind()函数;
3. 将套接字设置为监听模式等待连接请求,listen();
4. 配置好监听之后,调用accept()函数等待请求,当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字;
5. 用等待连接函数返回的套接字,调用send()和recv()客户端进行通信;
6. 处理完数据之后,就等待另一连接请求;
7. 关闭套接字,关闭加载的套接字库closesocket()、WSACleanup()。

2. 编码

头文件内容:
#pragma once
#include <winsock.h>
#include <string>

#define BufferSize 1024*1024	//发送的缓存的大小
// CTCPFileTrans

class CTCPFileTrans : public CWnd
{
	DECLARE_DYNAMIC(CTCPFileTrans)

public:
	CTCPFileTrans();
	CTCPFileTrans(std::string ip, int port);
	virtual ~CTCPFileTrans();

protected:
	DECLARE_MESSAGE_MAP()

private:
	SOCKADDR_IN addr;

public:
	CProgressCtrl* m_SendProcessBar;	//socket文件发送进度条
	CEdit* m_SendLog;		//socket文件发送打印日志

public:
	static DWORD WINAPI SendThreadProc(LPVOID lpParameter);    //创建线程去执行Socket操作
	static DWORD WINAPI ReceiveThreadProc(LPVOID lpParameter);    //创建线程去执行Socket操作
	CString* file_path;	//需要发送的文件路劲字符串
	int m_SendFileNum;	//需要发送的文件数目
	void SetSendFilePath(CString* file_name, const int file_num);	//发送字符串初始化,里面保存了需要发送的文件的路径

public:
	void ShowSocketMessage(int Error_Code, bool is_show=true);	//根据错误代码,提示相关错误
	bool TestConnection();					//检查设备连接

	//发送数据
public:
	std::string ip_address;		//接收方的IP地址
	unsigned int port_num;		//接收方的端口号
	SOCKET m_socket;			//发送的套接字变量

public:
	bool GetSendSocket();			//初始化SOCKET
	bool Sendfile(CString file_name);	//
	bool Sendfile(CString* file_name, const int file_count);	//

	//接收数据
public:
	bool GetRecSocket(int listen_num = 5);		//初始化监听调套接字
	bool ReceiveFile();			//
	SOCKET m_RecSocket;			//监听套接字
};
源代码文件内容:
// TCPFileTrans.cpp : 实现文件
//

#include "stdafx.h"
#include "File_Trans.h"
#include "TCPFileTrans.h"
#include <winsock.h>
#include <windows.h>


// CTCPFileTrans

IMPLEMENT_DYNAMIC(CTCPFileTrans, CWnd)

CTCPFileTrans::CTCPFileTrans()
{
	this->file_path = nullptr;
}

//
CTCPFileTrans::CTCPFileTrans(std::string ip, int port) : ip_address(ip), port_num(port)
{
	this->file_path = nullptr;
}


CTCPFileTrans::~CTCPFileTrans()
{
	if (file_path)
	{
		delete[] file_path;
		file_path = nullptr;
	}
}


BEGIN_MESSAGE_MAP(CTCPFileTrans, CWnd)
END_MESSAGE_MAP()

// CTCPFileTrans 消息处理程序
//************************************************************************
// 函数名称:    	InitSocket
// 访问权限:    	public 
// 创建日期:		2017/04/10
// 创 建 人:		
// 函数说明:		初始化SOCKET
// 返 回 值:   	bool
//************************************************************************
bool CTCPFileTrans::GetSendSocket()
{
	if (this->ip_address=="")
	{
		MessageBox(_T("SOCKET初始化过程中,输入的IP地址为空,请检查配置"), _T("错误"), MB_OK|MB_ICONERROR);
		return false;
	}
	if (this->port_num<=1024)
	{
		MessageBox(_T("SOCKET初始化过程中,输入的端口号与系统端口号冲突,请检查配置"), _T("错误"), MB_OK | MB_ICONERROR);
		return false;
	}

	WSAData data;
	if (0 != WSAStartup(MAKEWORD(2, 2), &data))						//初始化Windows Socket
	{
		int error_code(WSAGetLastError());	//获取错误代码
		CString error_num=_T("");
		error_num.Format(_T("%d"), error_code);
		MessageBox(_T("windows socket 初始化错误,错误代码:")+error_num, _T("错误"), MB_OK|MB_ICONERROR);
		WSACleanup();
		return false;
	}
	m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);	//网络流的TCP传输

	memset(&this->addr, 0, sizeof(SOCKADDR_IN));					//初始化结构体
	this->addr.sin_family = AF_INET;								//通信类型
	this->addr.sin_port = htons(this->port_num);							//设置端口号
	this->addr.sin_addr.S_un.S_addr = inet_addr(this->ip_address.c_str());		//设置ip地址
	if (0 != connect(m_socket, (SOCKADDR*)&this->addr, sizeof(this->addr)))			//连接到客户端
	{
		int error_code(WSAGetLastError());	//获取错误代码
		this->ShowSocketMessage(error_code);
		closesocket(this->m_socket);
		WSACleanup();
		return false;
	}

	return true;
}

//************************************************************************
// 函数名称:    	Sendfile
// 访问权限:    	public 
// 创建日期:		2017/04/10
// 创 建 人:		
// 函数说明:		TCP发送单个文件
// 函数参数: 	std::string file_name	文件的路径
// 返 回 值:   	bool
//************************************************************************
bool CTCPFileTrans::Sendfile(CString file_name)
{
	if (!this->GetSendSocket())
	{
		MessageBox(_T("发送单个文件,获取TCP连接失败!"), _T("错误"), MB_OK|MB_ICONERROR);
		return false;
	}

	HANDLE hFile = CreateFile(file_name, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0);	//获取文件句柄
	if (INVALID_HANDLE_VALUE == hFile)
	{
		MessageBox(_T("打开需要发送的本地文件失败!"), _T("错误"), MB_OK | MB_ICONERROR);
		return false;
	}	//有效性检查
	LARGE_INTEGER m_SendFileSize;			//文件的大小变量
	GetFileSizeEx(hFile, &m_SendFileSize);	//获取文件的字节大小
	LARGE_INTEGER m_SizeLeft2Send(m_SendFileSize);	//剩余需要发送的字节数

	CString m_FileSize;
	m_FileSize.Format(_T("%d"), m_SendFileSize.QuadPart);	//转换得到的大小

	//设置发送文件日志
	this->m_SendLog->SetWindowTextW(_T(" 发送文件:") + file_name + _T(" 开始..."));

	//发送文件的名字和大小
	CString m_SendStr = file_name + _T("&&&&&&&&") + m_FileSize;
	int send_length(m_SendStr.GetLength());
	std::string send_str = CStringA(m_SendStr);
	send(m_socket, send_str.c_str(), 2*m_SendStr.GetLength(), 0);

	//定义发送缓存
	char* m_SendBuffer = new char[BufferSize];
	memset(m_SendBuffer, 0, sizeof(char)*BufferSize);

	while (m_SizeLeft2Send.QuadPart > 0)
	{
		DWORD m_Bytes2Send(BufferSize);	//每次发送字节的大小
		DWORD m_ByteReaded(0);	//每次读取文件读取到的字节数 

		if (m_SizeLeft2Send.QuadPart <= m_Bytes2Send)
		{
			m_Bytes2Send = m_SizeLeft2Send.QuadPart;
		}	//如果需要传输的文件字节数小于发送的缓存大小,就将发送的缓存设置为文件的大小
		ReadFile(hFile, m_SendBuffer, m_Bytes2Send, &m_ByteReaded, 0);
		m_SizeLeft2Send.QuadPart -= m_ByteReaded;
		//更新发送进度条
		this->m_SendProcessBar->SetPos(int(m_SendFileSize.QuadPart-m_SizeLeft2Send.QuadPart)/m_SendFileSize.QuadPart);

		send(m_socket, m_SendBuffer, m_ByteReaded, 0);
	}

	//设置发送文件日志
	//更新发送进度条
	this->m_SendProcessBar->SetPos(100);
	this->m_SendLog->SetWindowTextW(_T(" 发送文件:") + file_name + _T(" 100%"));

	CloseHandle(hFile);	//关闭文件句柄
	closesocket(this->m_socket);
	WSACleanup();
	delete[] m_SendBuffer;
	m_SendBuffer = nullptr;

	return true;
}

//************************************************************************
// 函数名称:    	Sendfile
// 访问权限:    	public 
// 创建日期:		2017/04/10
// 创 建 人:		
// 函数说明:		TCP发送一组文件
// 函数参数: 	std::string * file_name	一组文件路径
// 函数参数: 	const int file_count	文件的数目
// 返 回 值:   	bool
//************************************************************************
bool CTCPFileTrans::Sendfile(CString* file_name, const int file_count)
{
	//if (!this->GetSendSocket())
	//{
	//	MessageBox(_T("发送一组文件,获取TCP连接失败!"), _T("错误"), MB_OK | MB_ICONERROR);
	//	return false;
	//}

	for (int i=0; i<file_count; i++)
	{
		if (!this->Sendfile(file_name[i]))
		{
			MessageBox(_T("在发送文件:") + file_name[i] + _T(" 时发生错误,发送失败!"),
				_T("错误"), MB_ICONERROR|MB_OK);
			return false;
		}
	}

	return true;
}

//************************************************************************
// 函数名称:    	SetSendFilePath
// 访问权限:    	public 
// 创建日期:		2017/04/12
// 创 建 人:		
// 函数说明:		发送字符串初始化,里面保存了需要发送的文件的路径
// 函数参数: 	CString * file_name
// 函数参数: 	const int file_num
// 返 回 值:   	void
//************************************************************************
void CTCPFileTrans::SetSendFilePath(CString* file_name, const int file_num)
{
	this->file_path = new CString[file_num];
	this->m_SendFileNum = file_num;
	for (int i=0; i<file_num; i++)
	{
		this->file_path[i] = file_name[i];
	}
}

//************************************************************************
// 函数名称:    	SendThreadProc
// 访问权限:    	public static 
// 创建日期:		2017/04/12
// 创 建 人:		
// 函数说明:		socket发送文件的线程
// 函数参数: 	LPVOID lpParameter
// 返 回 值:   	DWORD WINAPI
//************************************************************************
DWORD WINAPI CTCPFileTrans::SendThreadProc(LPVOID lpParameter)   //创建线程去执行Socket操作
{
	DWORD temp = 0;
	CTCPFileTrans* file_send = (CTCPFileTrans*)lpParameter;
	if (1 == file_send->m_SendFileNum)
	{
		file_send->Sendfile(file_send->file_path[0]);
	}
	else if (1 <= file_send->m_SendFileNum)
	{
		file_send->Sendfile(file_send->file_path, file_send->m_SendFileNum);
	}

	return temp;
}

//************************************************************************
// 函数名称:    	ReceiveThreadProc
// 访问权限:    	public static 
// 创建日期:		2017/04/12
// 创 建 人:		
// 函数说明:		socket文件接收线程
// 函数参数: 	LPVOID lpParameter
// 返 回 值:   	DWORD WINAPI
//************************************************************************
DWORD WINAPI CTCPFileTrans::ReceiveThreadProc(LPVOID lpParameter)    //创建线程去执行Socket操作
{
	DWORD temp = 0;
	CTCPFileTrans* file_send = (CTCPFileTrans*)lpParameter;
	while (true)
	{
		file_send->ReceiveFile();
	}

	return temp;
}

//************************************************************************
// 函数名称:    	GetRecSocket
// 访问权限:    	public 
// 创建日期:		2017/04/11
// 创 建 人:		
// 函数说明:		获取监听的Socket
// 返 回 值:   	bool
//************************************************************************
bool CTCPFileTrans::GetRecSocket(int listen_num)
{
	if (this->ip_address == "")
	{
		MessageBox(_T("SOCKET初始化过程中,输入的IP地址为空,请检查配置"), _T("错误"), MB_OK | MB_ICONERROR);
		return false;
	}
	if (this->port_num <= 1024)
	{
		MessageBox(_T("SOCKET初始化过程中,输入的端口号与系统端口号冲突,请检查配置"), _T("错误"), MB_OK | MB_ICONERROR);
		return false;
	}

	WSAData data;
	if (0 != WSAStartup(MAKEWORD(2, 2), &data))						//初始化Windows Socket
	{
		int error_code(WSAGetLastError());	//获取错误代码
		CString error_num = _T("");
		error_num.Format(_T("%d"), error_code);
		MessageBox(_T("windows socket 初始化错误,错误代码:") + error_num, _T("错误"), MB_OK | MB_ICONERROR);
		WSACleanup();
		return false;
	}
	m_RecSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);	//网络流的TCP传输

	memset(&this->addr, 0, sizeof(SOCKADDR_IN));					//初始化结构体
	this->addr.sin_family = AF_INET;								//通信类型
	this->addr.sin_port = htons(this->port_num);							//设置端口号
	this->addr.sin_addr.S_un.S_addr = inet_addr(this->ip_address.c_str());		//设置ip地址
	if (0 != bind(m_RecSocket, (SOCKADDR*)&this->addr, sizeof(this->addr)))	//绑定本地端口
	{
		int error_code(WSAGetLastError());	//获取错误代码
		CString error_num = _T("");
		error_num.Format(_T("%d"), error_code);
		MessageBox(_T("windows socket 绑定本地端口错误,错误代码:") + error_num, _T("错误"), MB_OK | MB_ICONERROR);
		WSACleanup();
		return false;
	}

	//配置监听
	if (0 != listen(m_RecSocket, listen_num))
	{
		int error_code(WSAGetLastError());	//获取错误代码
		CString error_num = _T("");
		error_num.Format(_T("%d"), error_code);
		MessageBox(_T("windows socket 绑定本地端口错误,错误代码:") + error_num, _T("错误"), MB_OK | MB_ICONERROR);
		WSACleanup();
		return false;
	}

	return true;
}

//************************************************************************
// 函数名称:    	ReceiveFile
// 访问权限:    	public 
// 创建日期:		2017/04/11
// 创 建 人:		
// 函数说明:		接收文件
// 返 回 值:   	bool
//************************************************************************
bool CTCPFileTrans::ReceiveFile()
{
	int len(sizeof(this->addr));
	SOCKET m_SocketAccept = accept(m_RecSocket, (SOCKADDR*)&this->addr, &len);	//接入套接字
	if (INVALID_SOCKET == m_SocketAccept)	//获取
	{
		int error_code(WSAGetLastError());	//获取错误代码
		CString error_num = _T("");
		MessageBox(_T("windows socket 接入套接字获取错误,错误代码:") + error_num, _T("错误"), MB_OK | MB_ICONERROR);
		WSACleanup();
		return false;
	}

	int receive_size(-1);
	char* m_ReveiveBuffer = new char[BufferSize];
	memset(m_ReveiveBuffer, 0, sizeof(char)*BufferSize);
	receive_size = recv(m_SocketAccept, m_ReveiveBuffer, BufferSize, 0);

	LARGE_INTEGER m_FileSize;	//文件大小
	HANDLE hFile;	//文件句柄
	std::string file_name;
	if (receive_size > 0)
	{
		std::string file_str = m_ReveiveBuffer;
		file_name = file_str.substr(0, file_str.find_first_of("&&&&&&&&"));
		file_name = file_name.substr(file_name.find_last_of("\\") + 1, file_name.length());
		std::string file_size = file_str.substr(file_str.find_first_of("&&&&&&&&") + 8, file_str.length());
		m_FileSize.QuadPart = std::atoi(file_size.c_str());
	}
	else{ return false; }

	hFile = CreateFile(CA2T(file_name.c_str()), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (INVALID_HANDLE_VALUE == hFile)
	{
		MessageBox(_T("创建下载文件:") + (CString)CA2T(file_name.c_str()) + _T("文件失败"), _T("错误"), MB_OK | MB_ICONERROR);
		return false;
	}

	while (m_FileSize.QuadPart > 0)
	{
		DWORD m_WirtedByte;
		receive_size = ::recv(m_SocketAccept, m_ReveiveBuffer, BufferSize, 0);
		::WriteFile(hFile, m_ReveiveBuffer, receive_size, &m_WirtedByte, NULL);
		m_FileSize.QuadPart -= m_WirtedByte;
	}

	CloseHandle(hFile);
}

//************************************************************************
// 函数名称:    	TestConnection
// 访问权限:    	public 
// 创建日期:		2017/04/11
// 创 建 人:		
// 函数说明:		检查网络连接
// 返 回 值:   	bool
//************************************************************************
bool CTCPFileTrans::TestConnection()
{
	if (this->ip_address == "")
	{
		MessageBox(_T("SOCKET初始化过程中,输入的IP地址为空,请检查配置"), _T("错误"), MB_OK | MB_ICONERROR);
		return false;
	}
	if (this->port_num <= 1024)
	{
		MessageBox(_T("SOCKET初始化过程中,输入的端口号与系统端口号冲突,请检查配置"), _T("错误"), MB_OK | MB_ICONERROR);
		return false;
	}

	WSAData data;
	if (0 != WSAStartup(MAKEWORD(2, 2), &data))						//初始化Windows Socket
	{
		int error_code(WSAGetLastError());	//获取错误代码
		CString error_num = _T("");
		error_num.Format(_T("%d"), error_code);
		MessageBox(_T("windows socket 初始化错误,错误代码:") + error_num, _T("错误"), MB_OK | MB_ICONERROR);
		WSACleanup();
		return false;
	}
	SOCKET m_socket_temp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);	//网络流的TCP传输

	memset(&this->addr, 0, sizeof(SOCKADDR_IN));					//初始化结构体
	this->addr.sin_family = AF_INET;								//通信类型
	this->addr.sin_port = htons(this->port_num);							//设置端口号
	this->addr.sin_addr.S_un.S_addr = inet_addr(this->ip_address.c_str());		//设置ip地址
	if (0 != connect(m_socket_temp, (SOCKADDR*)&this->addr, sizeof(this->addr)))			//连接到客户端
	{
		int error_code(WSAGetLastError());	//获取错误代码
		this->ShowSocketMessage(error_code);
		closesocket(m_socket_temp);
		WSACleanup();
		return false;
	}

	closesocket(m_socket_temp);
	WSACleanup();
	return true;
}

//************************************************************************
// 函数名称:    	ShowSocketMessage
// 访问权限:    	public 
// 创建日期:		2017/04/11
// 创 建 人:		
// 函数说明:		根据Socket返回回来的错误代码,弹出响应的消息提示框
// 函数参数: 	int Error_Code
// 返 回 值:   	void
//************************************************************************
void CTCPFileTrans::ShowSocketMessage(int Error_Code, bool is_show)
{
	if (!is_show)
	{
		return;
	}	//不显示错误代码提示

	int code(Error_Code);
	CString error_num = _T("");
	error_num.Format(_T("%d"), code);
	switch (code)
	{
	case WSAEALREADY:
		MessageBox(_T("非阻塞的连接请求正在特定的socket中处理,错误代码:") + error_num, _T("错误"), MB_OK | MB_ICONERROR);
		break;
	case WSAEADDRNOTAVAIL:
		MessageBox(_T("远程的连接地址不可用,错误代码:") + error_num, _T("错误"), MB_OK | MB_ICONERROR);
		break;
	case WSAEAFNOSUPPORT:
		MessageBox(_T("指定的传输类型在本socket中不受支持,错误代码:") + error_num, _T("错误"), MB_OK | MB_ICONERROR);
		break;
	case WSAECONNREFUSED:
		MessageBox(_T("socket连接请求被阻止,检查客户端是否开机启动,错误代码:") + error_num, _T("错误"), MB_OK | MB_ICONERROR);
		break;
	case WSAEFAULT:
		MessageBox(_T("当前本地地址配置对于当前传输协议不正确,错误代码:") + error_num, _T("错误"), MB_OK | MB_ICONERROR);
		break;
	case WSAEISCONN:
		MessageBox(_T("当前socket已经连接了,错误代码:") + error_num, _T("错误"), MB_OK | MB_ICONERROR);
		break;
	case WSAETIMEDOUT:
		MessageBox(_T("连接次超过了规定次数,错误代码:") + error_num, _T("错误"), MB_OK | MB_ICONERROR);
		break;
	default:
		break;
	}
}


  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是一个简单的 Windows 平台下使用 C 语言编写的 socket 编程实例: #include <stdio.h> #include <string.h> #include <winsock2.h> #define MAX_BUFFER_SIZE 1024 int main() { WSADATA wsaData; SOCKET serverSocket, clientSocket; struct sockaddr_in serverAddr, clientAddr; int clientAddrLen = sizeof(clientAddr); char buffer[MAX_BUFFER_SIZE]; char response[MAX_BUFFER_SIZE] = "Hello from server!"; // 初始化 Winsock if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { printf("Failed to initialize winsock.\n"); return 1; } // 创建服务器 socket serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket == INVALID_SOCKET) { printf("Failed to create server socket.\n"); WSACleanup(); return 1; } // 设置服务器地址和端口 serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; serverAddr.sin_port = htons(12345); // 绑定服务器地址和端口到 socket if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { printf("Failed to bind server address.\n"); closesocket(serverSocket); WSACleanup(); return 1; } // 开始监听客户端连接 if (listen(serverSocket, 5) == SOCKET_ERROR) { printf("Failed to listen for client connections.\n"); closesocket(serverSocket); WSACleanup(); return 1; } printf("Server is listening for incoming connections...\n"); // 接受客户端连接并进行通信 while (1) { // 等待客户端连接 clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen); if (clientSocket == INVALID_SOCKET) { printf("Failed to accept client connection.\n"); closesocket(serverSocket); WSACleanup(); return 1; } printf("Client connected: %s:%d\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port)); // 接收客户端发送的数据 memset(buffer, 0, sizeof(buffer)); if (recv(clientSocket, buffer, sizeof(buffer), 0) == SOCKET_ERROR) { printf("Failed to receive data from client.\n"); closesocket(clientSocket); closesocket(serverSocket); WSACleanup(); return 1; } printf("Received data from client: %s\n", buffer); // 发送响应给客户端 if (send(clientSocket, response, strlen(response), 0) == SOCKET_ERROR) { printf("Failed to send response to client.\n"); closesocket(clientSocket); closesocket(serverSocket); WSACleanup(); return 1; } printf("Response sent to client: %s\n", response); // 关闭客户端 socket closesocket(clientSocket); } // 关闭服务器 socket closesocket(serverSocket); // 清理 Winsock WSACleanup(); return 0; } 在该例子中,服务器创建一个 socket 监听客户端的连接请求。一旦有客户端连接进来,服务器会接收客户端发送的数据,然后返回一个固定的响应给客户端。 ### 回答2: 以下是一个使用Windows的C语言编写的简单socket编程实例: ```c #include <stdio.h> #include <winsock2.h> #define MAX_BUFFER_SIZE 1024 #define DEFAULT_PORT 8080 int main() { WSADATA wsaData; SOCKET listenSocket, clientSocket; struct sockaddr_in serverAddr, clientAddr; int clientAddrSize; char buffer[MAX_BUFFER_SIZE]; // 初始化Winsock库 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { printf("Winsock库初始化失败.\n"); return 1; } // 创建监听socket listenSocket = socket(AF_INET, SOCK_STREAM, 0); if (listenSocket == INVALID_SOCKET) { printf("创建socket失败.\n"); WSACleanup(); return 1; } // 设置服务器地址和端口 serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(DEFAULT_PORT); serverAddr.sin_addr.s_addr = INADDR_ANY; // 绑定socket到服务器地址和端口 if (bind(listenSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { printf("绑定socket失败.\n"); closesocket(listenSocket); WSACleanup(); return 1; } // 开始监听连接请求 if (listen(listenSocket, SOMAXCONN) == SOCKET_ERROR) { printf("监听连接请求失败.\n"); closesocket(listenSocket); WSACleanup(); return 1; } printf("服务器正在监听端口 %d ...\n", DEFAULT_PORT); while (1) { // 接受客户端连接请求 clientSocket = accept(listenSocket, (struct sockaddr *)&clientAddr, &clientAddrSize); if (clientSocket == INVALID_SOCKET) { printf("接收连接失败.\n"); closesocket(listenSocket); WSACleanup(); return 1; } // 从客户端读取数据 memset(buffer, 0, sizeof(buffer)); if (recv(clientSocket, buffer, MAX_BUFFER_SIZE, 0) == SOCKET_ERROR) { printf("接收数据失败.\n"); closesocket(clientSocket); WSACleanup(); return 1; } // 打印接收到的数据 printf("接收到来自客户端的数据: %s\n", buffer); // 发送响应给客户端 const char *response = "服务器已收到你的请求."; if (send(clientSocket, response, strlen(response), 0) == SOCKET_ERROR) { printf("发送响应失败.\n"); closesocket(clientSocket); WSACleanup(); return 1; } // 关闭客户端socket closesocket(clientSocket); } // 关闭监听socket closesocket(listenSocket); // 清理Winsock库 WSACleanup(); return 0; } ``` 这个例子创建了一个服务器程序,它通过在本地8080端口监听连接请求。一旦有客户端连接,服务器将接收该客户端的请求,并向客户端发送一个简单的响应。此例仅用于演示目的,并省略了错误处理和多线程处理。在实际开发中,您还需要根据需求添加适当的错误处理和多线程支持。 ### 回答3: 以下是一个简单的Windows C语言socket编程实例: #include <stdio.h> #include <stdlib.h> #include <winsock2.h> #define MAX_BUFFER_SIZE 1024 #define PORT 8080 int main() { WSADATA wsaData; SOCKET serverSocket, clientSocket; struct sockaddr_in serverAddress, clientAddress; char buffer[MAX_BUFFER_SIZE]; // 初始化Winsock库 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { fprintf(stderr, "Failed to initialize Winsock\n"); return 1; } // 创建服务器socket if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { fprintf(stderr, "Failed to create server socket\n"); WSACleanup(); return 1; } // 绑定服务器地址和端口 serverAddress.sin_family = AF_INET; serverAddress.sin_addr.s_addr = INADDR_ANY; serverAddress.sin_port = htons(PORT); if (bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR) { fprintf(stderr, "Failed to bind server socket\n"); closesocket(serverSocket); WSACleanup(); return 1; } // 监听客户端连接请求 if (listen(serverSocket, 1) == SOCKET_ERROR) { fprintf(stderr, "Failed to listen for client connections\n"); closesocket(serverSocket); WSACleanup(); return 1; } printf("Server is listening on port %d\n", PORT); // 接受客户端连接 int clientAddressSize = sizeof(clientAddress); if ((clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, &clientAddressSize)) == INVALID_SOCKET) { fprintf(stderr, "Failed to accept client connection\n"); closesocket(serverSocket); WSACleanup(); return 1; } printf("Client connected\n"); // 接收和发送数据 while (1) { memset(buffer, 0, sizeof(buffer)); if (recv(clientSocket, buffer, sizeof(buffer), 0) == SOCKET_ERROR) { fprintf(stderr, "Failed to receive data from client\n"); closesocket(clientSocket); closesocket(serverSocket); WSACleanup(); return 1; } printf("Received from client: %s", buffer); if (send(clientSocket, buffer, strlen(buffer), 0) == SOCKET_ERROR) { fprintf(stderr, "Failed to send data to client\n"); closesocket(clientSocket); closesocket(serverSocket); WSACleanup(); return 1; } } // 关闭socket和Winsock库 closesocket(clientSocket); closesocket(serverSocket); WSACleanup(); return 0; } 以上是一个简单的基于Windows平台的C语言socket编程示例。它创建了一个服务器端socket,并通过指定的端口监听客户端连接请求。一旦有客户端连接成功,服务器将接收来自客户端的数据,并将其发送回客户端。这个过程将持续进行,直到服务器或客户端关闭连接。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值