测试环境基于Win10 x64,Visual Studio
服务端代码
1. 初始化Winsock库;
2. 创建套接字;
3. 配置服务端地址;
4. 绑定套接字;
5. 监听连接;
6. 接收连接;
7. 发送数据给客户端;
8. 关闭连接。
#define _CRT_SECURE_NO_WARNINGS 1
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib") // 因为用到了Winsock库,所以需要引入这个lib文件
int main()
{
// 初始化Winsock库
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) // 初始化Winsock库,保证正确加载和卸载库
{
printf("初始化Winsock失败\n");
return 0;
}
// 创建套接字
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0); // 0代表默认协议
if (serverSocket == INVALID_SOCKET)
{
printf("创建套接字失败\n");
WSACleanup();
return 0;
}
// 配置服务端地址
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY; // INADDR_ANY为通配地址,0.0.0.0
serverAddr.sin_port = htons(8080);
// 绑定套接字
if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
{
printf("绑定失败\n");
closesocket(serverSocket);
WSACleanup();
return 0;
}
// 监听连接
if (listen(serverSocket, 10) == SOCKET_ERROR)
{
printf("监听失败\n");
closesocket(serverSocket);
WSACleanup();
return 1;
}
// 接收连接
SOCKET clientSocket = accept(serverSocket, NULL, NULL);
if (clientSocket == INVALID_SOCKET)
{
printf("连接失败\n");
closesocket(serverSocket);
WSACleanup();
}
printf("连接已建立\n");
// 发送数据给客户端
const char* message = "Hello, I'm Server!";
send(clientSocket, message, (int)strlen(message), 0);
// 关闭套接字
closesocket(clientSocket);
closesocket(serverSocket);
WSACleanup();
return 1;
}
客户端代码
1. 初始化Winsock库;
2. 创建套接字;
3. 配置服务端地址;
4. 连接到服务器;
5. 发送数据;
6. 接收服务端返回数据;
7. 关闭套接字。
#define _CRT_SECURE_NO_WARNINGS 1
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib") // 因为用到了Winsock库,所以需要引入这个lib文件
int main()
{
// 初始化Winsock库
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("初始化Winsock失败\n");
return 1;
}
// 创建套接字
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == INVALID_SOCKET) {
printf("创建套接字失败\n");
WSACleanup();
return 1;
}
// 配置服务端地址
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 服务端IP地址
serverAddr.sin_port = htons(8080); // 服务端端口号
// 连接到服务端
if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
printf("连接失败\n");
closesocket(clientSocket);
WSACleanup();
return 1;
}
// 发送数据
printf("已成功连接至服务器\n");
// 接收服务端发送的数据
char buffer[1024];
int bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0);
if (bytesRead > 0) {
buffer[bytesRead] = '\0';
printf("服务器: %s\n", buffer);
}
// 关闭套接字
closesocket(clientSocket);
WSACleanup();
return 1;
}
服务端
1. 初始化Winsock库;
2. 创建套接字;
3. 配置服务端地址;
4. 绑定套接字;
5. 接收数据;
6. 返回数据给客户端;
7. 关闭套接字。
#define _CRT_SECURE_NO_WARNINGS 1
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib") // 因为用到了Winsock库,所以需要引入这个lib文件
int main()
{
// 初始化Winsock库
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) // 初始化Winsock库,保证正确加载和卸载库
{
printf("初始化Winsock失败\n");
return 0;
}
// 创建套接字
SOCKET serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (serverSocket == INVALID_SOCKET)
{
printf("创建套接字失败\n");
WSACleanup();
return 0;
}
// 配置服务端地址
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY; // INADDR_ANY为通配地址,0.0.0.0
serverAddr.sin_port = htons(8080);
// 绑定套接字
if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
{
printf("绑定失败\n");
closesocket(serverSocket);
WSACleanup();
return 0;
}
// 接收数据
char buffer[1024];
struct sockaddr_in clientAddr;
int clientAddrSize = sizeof(clientAddr);
int bytesRead = recvfrom(serverSocket, buffer, sizeof(buffer), 0, (struct sockaddr*)&clientAddr, &clientAddrSize);
if (bytesRead > 0)
{
buffer[bytesRead] = '\0';
printf("客户端: %s\n", buffer);
// 发送数据给客户端
const char* message = "Hello from server!";
sendto(serverSocket, message, (int)strlen(message), 0, (struct sockaddr*)&clientAddr, sizeof(clientAddr));
}
// 关闭套接字
closesocket(serverSocket);
WSACleanup();
return 1;
}
客户端
1. 初始化Winsock库;
2. 创建套接字;
3. 配置服务端地址;
4. 发送数据给服务端;
5. 接收服务端发送的数据;
6. 关闭套接字。
#define _CRT_SECURE_NO_WARNINGS 1
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib") // 因为用到了Winsock库,所以需要引入这个lib文件
int main()
{
// 初始化Winsock库
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("初始化Winsock失败\n");
return 1;
}
// 创建套接字
SOCKET clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (clientSocket == INVALID_SOCKET) {
printf("创建套接字失败\n");
WSACleanup();
return 1;
}
// 配置服务端地址
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务端IP地址
// serverAddr.sin_addr.s_addr = INADDR_BROADCAST; // 如果给其他主机发消息,用这个
serverAddr.sin_port = htons(8080); // 服务端端口号,这里最好只用htons,因为它针对16位的主机字节,端口一般都是16位
// 发送数据给服务端
const char* message = "服务端你好,我是客户端!\n";
sendto(clientSocket, message, strlen(message), 0, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
// 接收服务端发送的数据
char buffer[1024];
struct sockaddr_in fromAddr;
int fromAddrSize = sizeof(fromAddr);
int bytesRead = recvfrom(clientSocket, buffer, sizeof(buffer), 0, (struct sockaddr*)&fromAddr, &fromAddrSize);
if (bytesRead > 0) {
buffer[bytesRead] = '\0';
printf("服务器: %s\n", buffer);
}
// 关闭套接字
closesocket(clientSocket);
WSACleanup();
return 1;
}
贴一个自己项目当中用到的实例,该代码是用来和另一台主机通信的,通信要求如下
1. 目标设备接收数据的端口是65001;
2. 目标设备接收到数据后会有返回;
3. 目标设备只接收18个字节的数据包;
4. 目标设备只接收从65000端口发的数据,并且后续返回的数据也会返回到65000端口
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib") // 链接到Winsock库
#define ENTER_CODE 0xEB90149F
int main() {
WSADATA wsaData;
SOCKET udpSocket;
// 初始化Winsock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("初始化 Winsock 失败.\n");
return -1;
}
// 创建UDP套接字
udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (udpSocket == INVALID_SOCKET) {
printf("创建 socket 失败 : %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
// 设置广播
int on = 1;
setsockopt(udpSocket, SOL_SOCKET, SO_BROADCAST, (char*)&on, sizeof(on));
// 设置本地地址
struct sockaddr_in localaddr;
memset((char*)&localaddr, 0, sizeof(localaddr));
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(65000);
localaddr.sin_addr.s_addr = inet_addr("192.168.10.1");
// 将套接字绑定到本地地址
if (bind(udpSocket, (struct sockaddr*)&localaddr, sizeof(localaddr)) == SOCKET_ERROR) {
printf("绑定失败, error code : %d\n", WSAGetLastError());
}
// 设置服务器地址
struct sockaddr_in serverAddr;
int serverAddrSize = sizeof(serverAddr);
memset((char*)&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_BROADCAST;
serverAddr.sin_port = htons(65001);
// 将数据填充到buff中,注意网络字节序的转换
unsigned char send_buff[200] = {0x00};
int a = ENTER_CODE;
memcpy(send_buff, &a, 4);
// 为数据接收做准备
unsigned char recv_buff[1072];
struct sockaddr_in clientAddr;
int clientAddrSize = sizeof(clientAddr);
int recvSize;
memset(recv_buff, 0, sizeof(recv_buff));
while (1)
{
// 发送数据
sendto(udpSocket, (char*)send_buff, 18, 0, (struct sockaddr*)&serverAddr, serverAddrSize);
if (sendto(udpSocket, (char *)send_buff, 18, 0, (struct sockaddr*)&serverAddr, serverAddrSize) == SOCKET_ERROR) {
printf("数据发送失败, error code : %d\n", WSAGetLastError());
}
else { printf("发送成功 "); }
for (int i = 0; i < 10; i++)
{
printf(" %02X ", send_buff[i]);
}
printf("\n");
Sleep(500);
recvSize = recvfrom(udpSocket, (char*)recv_buff, sizeof(recv_buff), 0, (struct sockaddr*)&clientAddr, &clientAddrSize);
if (recvSize == SOCKET_ERROR) {
printf("接收数据失败, error code : %d\n", WSAGetLastError());
}
else if (recvSize > 0) {
printf("接收到的数据: ");
for (int i = 0; i < recvSize; i++) {
printf("%02X ", recv_buff[i]);
}
printf("\n");
}
}
// 清理
closesocket(udpSocket);
WSACleanup();
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <windows.h>
#include <time.h>
DWORD WINAPI threadFunction(LPVOID lpParam)
{
int flag = 0;
while (1)
{
printf("线程功能\n");
if (flag > 10) { break; }
else { flag += 1; }
Sleep(100);
}
return 0;
}
DWORD WINAPI threadFunction2(LPVOID lpParam)
{
int flag = 0;
while (1)
{
printf("线程功能2222222\n");
if (flag > 15) { break; }
else { flag += 1; }
Sleep(100);
}
return 0;
}
int main()
{
HANDLE t1; // 创建句柄
HANDLE t2; // 创建句柄
/*
LPVOID pParam1; // 参数指针
LPVOID pParam2; // 参数指针
*/
// 创建线程
t1 = CreateThread(
NULL, // 默认安全性,在大多数情况下,这个参数设置为NULL
0, // 指定线程的堆栈大小,如果这个参数设为0,那么系统会为新线程分配默认的堆栈大小
threadFunction, // 是一个函数指针,指向线程要执行的代码
NULL, // 线程函数的参数
0, // 指定如何创建线程,这个参数被设置为0,这意味着线程将立即开始执行
NULL // 这个参数是一个输出参数,它接收新线程的ID
);
// 创建线程2
t2 = CreateThread(
NULL, // 默认安全性,在大多数情况下,这个参数设置为NULL
0, // 指定线程的堆栈大小,如果这个参数设为0,那么系统会为新线程分配默认的堆栈大小
threadFunction2, // 是一个函数指针,指向线程要执行的代码
NULL, // 线程函数的参数
0, // 指定如何创建线程,这个参数被设置为0,这意味着线程将立即开始执行
NULL // 这个参数是一个输出参数,它接收新线程的ID
);
if (t1 == NULL | t2 == NULL)
{
printf(stderr, "线程创建失败\n");
return 0;
}
// 等待线程结束
WaitForSingleObject(t1, INFINITE);
WaitForSingleObject(t2, INFINITE);
// 关闭线程句柄
CloseHandle(t1);
CloseHandle(t2);
return 1;
}