C语言创建TCP连接

[TCP编程]

服务端:

  1、加载套接字,版本号,创建协议:socket();(服务端地址可接受任何IP)
	2、绑定IP,端口  接口sockaddr_in  方法:bind();
	3、增加监听 list;
	4、循环接收数据  accept()接受客户端的请求;
	4、发送,接受:send(),recv().
#include <stdio.h>
#include <winSock2.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <time.h>
#pragma comment(lib,"ws2_32.lib")

#define SERVER_PORT 3947

bool isRunning = false;

SOCKET ServerSocket;
SOCKET ClientSoket;

sockaddr_in serverAddr_in;
sockaddr_in clientAddr_in;

DWORD wVertionRequestion = MAKEWORD(2,2);
WSADATA wsaData;

//接受的信息
char rec[255];


typedef struct CLIENT
{
	SOCKET client;
	char name[20];
	bool isFightding;
	SOCKET enemy;
	char enemyName[20];
	struct CLIENT *next;
}ClientNode,*CLientList;

typedef struct CLIENTSERVER
{
	int size;
	CLientList head;
}ClientServer;

void sendMsg(char *content, char x, char y)
{
	CLientList p = SClient.head->next;
	char name[255];
	char infor[255];
	split(content,':',name,infor);
	if (SClient.size <= 1)
	{
		return;
	}
	while (p&&strcmp(name, p->name))
	{
		p = p->next;
	}
	
	if (p != NULL)
	{

    	send(p->enemy, infor, strlen(infor), 0);
	}
	return;
}

//接受信息线程
DWORD WINAPI reciveMsg(LPVOID parameter)
{
	
	int rc;
	CLientList p;
	while (isRunning)
	{
		p = SClient.head->next;
		
		while (p)
		{
			rc = recv(p->client, rec, sizeof(rec), 0);
			if (rc >= 0)
			{
				rec[rc] = 0x00;
				sendMsg(rec, 1, 2);
			}
			if (rc < 0)
			{
				printf("%s已退出\n", p->name);
				removeClient(p->name);
				break;
			}
			p = p->next;
		}
		
	}
	return NULL;
}

//添加客户端线程
DWORD WINAPI startHere(LPVOID parameter)
{
	char name[20];
	int len;
	
	int add_len = sizeof(clientAddr_in);

	while (true)
	{

		printf("请等候...\n");
		ClientSoket = accept(ServerSocket, (sockaddr *)&clientAddr_in, &add_len);

		if (ClientSoket == INVALID_SOCKET)
		{
			perror("accept");
		}
		isRunning = true;

		//得到客户端的名称...  
		len = recv(ClientSoket, name, sizeof(name), 0);
		if (len > 0)
		{
			name[len] = 0x00;
		}
		if (len < 0)
		{
			isRunning = false;
		}
		printf("建立了与客户端:%s 的链接 IP地址:%s\n", name, inet_ntoa(clientAddr_in.sin_addr));
		createClientList(SClient.head, ClientSoket, name);

		SClient.size++;
		if (SClient.size % 2 == 0)
		{
			matchEnemy(ClientSoket);
		}
		//CreateThread(NULL,0,sendMsg,NULL,0,NULL);
		CreateThread(NULL, 0, reciveMsg, NULL, 0, NULL);

		displayClient(SClient.head);
	}
		
	return NULL;

}


int main()
{
	//随机种子
	srand((int)time(0));
	if (WSAStartup(wVertionRequestion, &wsaData) != 0)
	{
		perror("load socket ");
	}

	//创建套接字
	ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	//绑定IP和端口号
	serverAddr_in.sin_family = AF_INET;
	serverAddr_in.sin_port = htons(SERVER_PORT);
	serverAddr_in.sin_addr.s_addr = INADDR_ANY;
	if (bind(ServerSocket, (sockaddr *)&serverAddr_in, sizeof(serverAddr_in)) == SOCKET_ERROR)
	{
		perror("bind ");
	}
	//增加监听
	if (listen(ServerSocket, 5) == INVALID_SOCKET)
	{
		perror("listen ");
	}
		
	CreateThread(NULL, 0, startHere, NULL, 0, NULL);

	while (true)
	{

	}
	return 0;
}
## 客服端:
		1、加载套接字,版本号,创建协议:socket();(设置IP,地址族...2、与服务器建立链接  connect();
		3、发送,接受:send(),recv().**
```c
#include <winSock2.h>
#include <stdio.h>
#include <conio.h>

#pragma comment(lib,"ws2_32.lib")

#define SERVER_PORT 3947

//用户注册一个账号,方便局域网中操作
char name[20];

SOCKET ServerSocket;

sockaddr_in serveraddr_in;
DWORD wVertionRequestied = MAKEWORD(2,2);
WSADATA wsaData;

//创建接受信息的线程随时接受信息
DWORD WINAPI recive(LPVOID parameter)
{
	char x, y;
	int rc;
	char rec[255];
	while (true)
	{
	
		rc = recv(ServerSocket, rec, sizeof(rec), 0);
		if (rc > 0)
		{
			rec[rc] = 0x00;
			printf("%s\n",rec);
		}
	}
}

DWORD WINAPI sendMsg(LPVOID parameter)
{
	char sendData[255];
	char pos[5];
	int name_len = strlen(name);


	while (true)
	{
		scanf("%s", pos);
		strcat(name, ":");
		strcat(name, pos);

		send(ServerSocket, name, strlen(name), 0);
		name[name_len] = 0x00;
	}

	return NULL;
}

int main()
{
	
	//加载套接字
	int nErr = WSAStartup(wVertionRequestied, &wsaData);
	if (nErr != 0)
	{
		perror("load socket ");
	}

	ServerSocket = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);

	serveraddr_in.sin_family = AF_INET;
	serveraddr_in.sin_port = htons(SERVER_PORT);
	serveraddr_in.sin_addr.s_addr = inet_addr("127.0.0.1");

	if (connect(ServerSocket, (sockaddr *)&serveraddr_in, sizeof(serveraddr_in)) == SOCKET_ERROR)
	{
		perror("connect ");
	}
	//开启接收信息线程
	CreateThread(NULL,0,recive,NULL,NULL,NULL);

	//第一次发送名字,让服务端添加一个客户端进入
	printf("请输入你的姓名:");
	scanf("%s", name);
	send(ServerSocket,name,strlen(name),0);
	
	printf("对话框:\n");
	printf("##################################################################\n");
	
	CreateThread(NULL, 0, sendMsg, NULL, 0, NULL);

	while (true)
	{

	}
	closesocket(ServerSocket);
	WSACleanup();	
}
### NodeMCU-ESP8266 通过 TCP 协议与后端服务器通信 为了实现 NodeMCU (基于 ESP8266) 作为 TCP 客户端与后端服务器之间的通信,通常需要完成以下几个部分的工作: 1. **Wi-Fi 连接配置**: 使用 `ESP8266WiFi` 库来连接到 Wi-Fi 网络。 2. **TCP 客户端初始化**: 创建一个客户端对象用于建立与远程服务器的 TCP 链接。 3. **数据传输逻辑**: 实现数据的发送和接收功能。 以下是完整的示例代码以及说明[^1]: #### 示例代码 ```cpp #include <ESP8266WiFi.h> // 替换为实际的 Wi-Fi 名称和密码 const char* ssid = "Your_SSID"; const char* password = "Your_PASSWORD"; // 后端服务器 IP 地址或域名, 及其监听端口号 IPAddress serverIP(192, 168, 1, 10); // 或者 const char* serverAddress = "example.com" const int serverPort = 80; WiFiClient client; void setup() { Serial.begin(115200); // 连接到 Wi-Fi 网络 WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("Connected to WiFi"); // 尝试连接到服务器 if (!client.connect(serverIP, serverPort)) { Serial.println("Connection failed"); return; } Serial.println("Connected to the server!"); } void loop() { // 发送数据到服务器 String message = "Hello from ESP8266!"; client.println(message); // 接收来自服务器的数据并打印至串口监视器 if (client.available()) { String response = client.readStringUntil('\n'); Serial.print("Server Response: "); Serial.println(response); } delay(5000); // 每隔 5 秒钟发送一次消息 } ``` --- #### 关键点解析 1. **Wi-Fi 连接** - 使用 `WiFi.begin()` 函数尝试连接指定 SSID 的无线网络。当返回状态为 `WL_CONNECTED` 表明已成功接入互联网。 2. **创建客户端实例** - 声明了一个全局变量 `WiFiClient client` 来表示当前节点作为一个 TCP 客户端的身份。调用 `connect(ip_address, port)` 方法发起对目标主机的服务请求[^3]。 3. **数据交互过程** - 调用了 `println()` 方法向远端写入字符串形式的消息;而读取响应则依赖于检测缓冲区是否有新到达的内容(`available()`) 并提取它 (`readStringUntil('\n')`)[^3]。 4. **错误处理机制** 如果未能成功建立起链接,则会在控制台输出相应的提示信息以便调试分析原因所在。 --- #### 注意事项 - 确保所使用的路由器支持 DHCP 功能自动分配 IP 给设备或者手动设置静态地址参数。 - 测试阶段建议开启串行接口监控工具观察程序执行流程中的日志记录情况便于排查潜在问题。 - 对应的目标服务器需处于可被外部访问的状态并且开放对应端口接受外来连接请求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值