TCP/IP C 语言实现单个客户端和服务端 TCP 通信

这篇具有很好参考价值的文章主要介绍了TCP/IP C 语言实现单个客户端和服务端 TCP 通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 这是多线程服务端

#include <stdio.h>
#include <winsock2.h>
#include <pthread.h>
#include <string.h>
#include <conio.h>
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable : 4996)	
// 客户端结构体
typedef struct ThreadNode
{
	int index;
	pthread_t* Thread;
	SOCKET Client;
	struct ThreadNode * next;
	ThreadNode()
	{
		index = 0;
		this->next = NULL;
	}
} hThread;
// 增加客户端结构体
hThread *clientHeadNote, *clientEndNote;
hThread * addClient()
{
	hThread * ClientNote = new hThread();
	return ClientNote;
}
// 每个建立链接的客户端分配一个函数,每个线程运行一个这样的函数
void* ThreadClient(void*)
{
	if (clientEndNote == NULL)
	{
		printf("empty Link\n");
		return 0;
	}
	char revData[255];
	SOCKET sClient = clientEndNote->Client;
	printf("client logged in \n");
	while (1)
	{
		int ret = recv(sClient, revData, 255, 0);		// 接收数据
		if (ret > 0)
		{
			revData[ret] = 0x00;
			printf(revData);
			printf("\n");
			if (strcmp("log_out", revData) == 0)		// 新功能:加入客户端控制签退
			{
				char a[255];
				strcpy(a, "已注销\n");
				send(sClient, a, 255, 0);				// 反馈:向客户端sClienr发送“已注销”消息,发送长度为255个字节,1是指不阻塞。
				closesocket(sClient);
				printf("签退成功\n");
			}
			else
			{
				char a[255];
				strcpy(a, "服务器已收到消息\n");
				send(sClient, a, 255, 0);
			}
		}
	}
	closesocket(sClient);
}

int main(int argc, char* argv[])
{
	// 初始化WSA
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	if (WSAStartup(sockVersion, &wsaData) != 0)
	{
		return 0;
	}
	// 创建套接字:AF_INET:TCP/IP 协议,数据流,TCP 传输 
	SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (slisten == INVALID_SOCKET)
	{
		printf("socket error !");
		return 0;
	}

	//绑定IP和端口
	sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(8888);								// 端口和客户端端口要相同,否则链接建立不上
	sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);			// 这个是any指的是不限制访问IP
//	char loa[16] = "192.168.15.189";						// 这是指定 IP发送数据 
//	sin.sin_addr.S_un.S_addr = inet_addr(loa);				// 加入指定 IP 


//	初始化slisten,加载上面代码设置的属性。
	if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)	// 把sin强制类型转换为sockadd,sin原来是sockaddr_in类型
	{
		printf("bind error !");
	}
	//开始监听
	if (listen(slisten, 5) == SOCKET_ERROR)
	{
		printf("listen error !");
		return 0;
	}
//	以上可以认为是建立服务器联系的固定格式


//这里是多线程服务器,接受多个客户端,可以对比单线程看看多了什么,哪些函数的位置调整了
	sockaddr_in remoteAddr;
	int nAddrlen = sizeof(remoteAddr);
	while (true)
	{
		printf("等待连接...\n");
		SOCKET sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);
		if (sClient == INVALID_SOCKET)
		{
			printf("accept error !");
		}
		else
		{
			printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));
			if (clientHeadNote == NULL)
			{
				clientHeadNote = addClient();
				clientEndNote = clientHeadNote;
			}
//			必须要先创建给end节点,然后再创建线程,因为线程的参数通过全局变量传入,而不是通过线程生成函数传入
//			原来线程参数除了 pthread_create()还能通过全局变量传参数
			hThread* clientnode = (hThread*)malloc(sizeof(hThread));								// 创建客户端结构体 
			clientnode->Client = sClient;
			clientnode->next = NULL;
			clientHeadNote->next = clientnode;
			clientEndNote = clientnode;
			clientnode->Thread = (pthread_t*)malloc(sizeof(pthread_t));								// 创建线程变量 
			clientnode->index = pthread_create(clientnode->Thread, NULL, ThreadClient, NULL);		// 创建线程并执行 
		}
	}
	printf("server is closing\n");
	hThread * p;
	while (clientHeadNote)  			 //释放占用的内存空间
	{
		p = clientHeadNote;
		clientHeadNote = clientHeadNote->next;
		delete p;
	}
	closesocket(slisten);
	WSACleanup();
	return 0;
}

这是单线程服务端 

#include <stdio.h>
#include <winsock2.h>
#include <conio.h>
#pragma comment(lib,"ws2_32.lib")
#pragma waring(disable :4996)
int main()
{
	WORD sockVersion = MAKEWORD(2,2);
	WSADATA wsaData;
	if(WSAStartup(sockVersion,&wsaData)!=0)
	{
		printf("版本与结构体不匹配\n");
		return 0;
	}
	SOCKET slisten = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(slisten==INVALID_SOCKET)
	{
		printf("socket error\n");
		return 0;
	}
	sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(8888);
	sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

	if(bind(slisten,(LPSOCKADDR)&sin,sizeof(sin))==SOCKET_ERROR)
	{
		printf("bind error\n");
	}
	if(listen(slisten,5)==SOCKET_ERROR)
	{
		printf("listen error\n");
		return 0;
	}
	sockaddr_in remoteAddr;
	int nAddrlen=sizeof(remoteAddr);
	char rev[255];
	char sen[244];
	strcpy(sen,"okk\n");
	printf("等待连接\n");
	SOCKET sClient = accept(slisten,(SOCKADDR*)&remoteAddr,&nAddrlen);
	if(sClient==INVALID_SOCKET)
	{
		printf("accpet error\n");
	}

	int ret=0;
	while(true)
	{
		ret=0;
		ret =recv(sClient,rev,255,0);
		if(ret>0)
		{
			printf("recieve\n");
			printf("ret = %d\n",ret);
			printf("消息为:%s\n",rev);
			send(sClient,sen,255,0);			// 0 代表阻塞发送,缓存起来,按顺序一个一个发
			strcpy(rev,"");						// 清空旧数据 
		}
		Sleep(100);
	}
}

这是客户端

#include <winsock2.h>
#include <stdio.h>
#include <pthread.h>
#pragma  comment(lib,"ws2_32.lib")
#pragma warning(disable : 4996)	
//格式和服务端一样
int main(int argc, char* argv[])
{
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA data;
	if (WSAStartup(sockVersion, &data) != 0)
	{
		return 0;
	}
	SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sclient == INVALID_SOCKET)
	{
		printf("无效的 socket !");
		return 0;
	}
	sockaddr_in serAddr;
	serAddr.sin_family = AF_INET;	// 表示使用IPv4地址协议 https://blog.csdn.net/u012736362/article/details/130392547
	serAddr.sin_port = htons(8888);
	char loa[16] = "127.0.0.1";		// 对方IP地址。当服务器的电脑的IP , win建+r 输入cmd,打开命令行,输入再直接 ipconfig/all可查看IP。
	serAddr.sin_addr.S_un.S_addr = inet_addr(loa);// IP是读取目标机器的IP,由于一台电脑当服务器和客户端,127.0.0.1是自回路,自己发送给自己


//链接发消息
	while(connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
	{
		//主动连接服务器
		printf("连接错误 !\n");
		Sleep(1000);
	}
	puts("连接成功!!");
	puts("你现在可以向服务器发送信息:");
	char sendData[100];
	char recData[255];
	while (1)
	{
		scanf("%s",sendData);
		send(sclient, sendData, strlen(sendData), 0);		// 发送消息 0 代表阻塞 1 代表不阻塞 
		int ret = recv(sclient, recData, 255, 0);			// 接收消息 0 代表不执行这句,下面的都不执行 
		if (ret > 0)
		{
			printf(recData);
		}
	}
	closesocket(sclient);
	WSACleanup();
	return 0;
}

 文章来源地址https://www.toymoban.com/news/detail-832769.html

到了这里,关于TCP/IP C 语言实现单个客户端和服务端 TCP 通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • TCP IP网络编程(四) 基于TCP的服务器端、客户端

    TCP/IP协议栈 ​ TCP/IP协议栈 TCP/IP协议栈共分为4层,可以理解为数据收发分成了4个层次化过程。 ​ TCP协议栈 ​ UDP协议栈 链路层 链路层是物理连接领域标准化的结果,也是最基本的领域,专门定义LAN、WAN、MAN等网络标准。两台主机通过网络进行数据交换,这需要像下图所示

    2024年01月16日
    浏览(55)
  • 《TCP/IP网络编程》阅读笔记--基于TCP的服务器端/客户端

    目录 1--TCP/IP协议栈 2--TCP服务器端默认函数调用顺序 3--TCP客户端的默认函数调用顺序 4--Linux实现迭代回声服务器端/客户端 5--Windows实现迭代回声服务器端/客户端 6--TCP原理 7--Windows实现计算器服务器端/客户端         TCP/IP协议栈共分 4 层,可以理解为数据收发分成了 4 个层

    2024年02月10日
    浏览(64)
  • TCP IP网络编程(五) 基于TCP的服务器端、客户端 (补充)

    回声客户端出现的问题 在上一节基于TCP的服务器端、回声客户端中,存在问题: 如果数据太大,操作系统就有可能把数据分成多个数据包发送到客户端,客户端有可能在尚未收到全部数据包时就调用read函数 问题出在客户端,而不是服务器端,先来对比一下客户端与服务器端

    2024年02月09日
    浏览(67)
  • QT学习TCP/IP通信(一个服务端对多个客户端)

    QT学习TCP/IP通信(一个服务端对多个客户端) 一、服务端: 1.创建QTcpServer对象 2.启动服务器(监听)调用成员方法listen(QHostAddress::Any,端口号) 3.定义一个QLis容器对象存储客户信息; 4.当有客户端链接时候会发送newConnection信号,触发槽函数接受链接(得到一个与客户端通信的

    2024年02月11日
    浏览(47)
  • 用C语言搭建TCP服务器/客户端

    1.TCP流程图 2.TCP编程 服务器 客户端         以上就是用c语言搭建的tcp服务器和客户端,IP地址的地方可以根据自己本机的IP地址去修改(在命令提示符中可以使用ifconfig命令查看本机IP地址),端口号用的是6666,也可自己修改,但是IP地址和端口号服务器和客户端必须一至。

    2024年02月09日
    浏览(45)
  • FPGA实现10G万兆网TCP/IP 协议栈,纯VHDL代码编写,提供服务器和客户端2套工程源码和技术支持

    目前网上fpga实现udp协议的源码满天飞,我这里也有不少,但用FPGA纯源码实现TCP的项目却很少,能上板调试跑通的项目更是少之又少,甚至可以说是凤毛菱角,但很不巧,本人这儿就有一个; 本设采用纯VHDL实现了10G万兆网TCP/IP协议栈,该协议栈分为TCP服务器核客户端,没有使

    2024年02月09日
    浏览(66)
  • C语言再学习 -- C语言搭建TCP服务器/客户端

    TCP/UDP讲过~ 参看:UNIX再学习 – TCP/UDP 客户机/服务器 参看:UNIX再学习 – 网络IPC:套接字 这里记录一下可用的TCP服务器和客户端代码。 参看:用C语言搭建TCP服务器/客户端

    2024年01月20日
    浏览(74)
  • C++网络通信实例(TCP/IP协议,包括服务端与客户端通信)

    创作不易 觉得有帮助请点赞关注收藏 TCP/IP是当下网络协议栈中的主流协议 TCP属于传输层的协议  可靠传输 包括经典的三次握手等等 IP协议是网络层协议 尽全力传输但不可靠 学过计算机网络的同学们对这个应该比较熟悉 以下是使用C++进行网络通信的实例  服务端 主要使用

    2024年02月14日
    浏览(50)
  • socket的使用 | TCP/IP协议下服务器与客户端之间传送数据

    谨以此篇,记录TCP编程,方便日后查阅笔记 注意:用BufferedWriter write完后,一定要flush;否则字符不会进入流中。去看源码可知:真正将字符写入的不是write(),而是flush()。 服务器端代码: 客户端代码: 运行后结果: 服务器端: 客户端: 参考资料: https://www.bilibili.com/vid

    2024年02月09日
    浏览(60)
  • 《TCP/IP网络编程》阅读笔记--基于UDP的服务器端/客户端

    目录 1--TCP和UDP的主要区别 2--基于 UDP 的数据 I/O 函数 3--基于 UDP 的回声服务器端/客户端 4--UDP客户端Socket的地址分配 5--UDP存在数据边界 6--UDP已连接与未连接的设置 ① TCP 提供的是可靠数据传输服务,而 UDP 提供的是不可靠数据传输服务; ② UDP 在结构上比 TCP 更简洁,其不会

    2024年02月09日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包