基于TCP套接字实现的简单Demo

由于代码的注释已经很详尽了,所以这里不再作过多说明.

仅仅贴出代码和结果图.


值得注意的是必须先启动server程序再启动client.


Server:

#include <WINSOCK2.H>	//套接字库
#include <stdio.h>

#define PORT       6000 //服务器端口
#define MSGSIZE    1024 //收发缓冲区的大小

#pragma comment(lib, "ws2_32.lib") //链接静态库

DWORD WINAPI FunThread(LPVOID); //创建一个线程,专门用来接收数据

SOCKET      sClient; //连接所用套节字
SOCKET      sListen; //监听套接字
SOCKADDR_IN client; //保存客户的地址信息
int         iaddrSize = sizeof(SOCKADDR_IN);
 
int main()
{

	WSADATA     wsaData;		//WSADATA结构体中主要包含了系统所支持的Winsock版本信息
	SOCKADDR_IN local;		//定义本地套接字地址
	char        s_Message[MSGSIZE]; //收发缓冲区

	WSAStartup(0x0202, &wsaData); //初始化套接字库
	
	sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//创建服务器监听套节字。TCP协议
	
	local.sin_family = AF_INET; //AF_INET指明使用TCP/IP协议族
	local.sin_port = htons(PORT);//指明连接服务器的端口号
	local.sin_addr.s_addr = htonl(INADDR_ANY);//自动获取本机地址

	bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));//地址绑定到套接字
	
	listen(sListen, 1);//开始监听
	
	sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);//建立连接,返回用于连接的套接字
	printf("Accepte client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));//输出客户端的IP地址和端口


	HANDLE hThread=CreateThread(NULL,0,FunThread,0,0,0);//运行至此创建专门的接收线程用于接收客户端发送
								//的数据,在监听主线程上创建一个新的数据接收线程
	CloseHandle(hThread);//关闭线程句柄


	//用于从服务器端向客户端发送数据
	while (TRUE)
	{
		printf("Server Send:");
		//从键盘输入
		gets(s_Message);                        
		//发送数据
		send(sClient, s_Message, strlen(s_Message), 0); 
	}
	return 0; 
} 


//当接收数据时调用此线程函数
DWORD WINAPI FunThread(LPVOID)
{   
	char c_Message[MSGSIZE]; //接收数据缓冲区
	int ret; //接收字节的个数
	while (TRUE)
	{  
		ret = recv(sClient, c_Message, MSGSIZE, 0);//接收数据到缓冲区
		
		//判断是否成功接收,如果未成功接收则重启监听,将原缓冲区的数据归零
		if(ret==SOCKET_ERROR)
		{
			printf("\nclient is closed!");
			
			sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);//重新开始监听
			printf("\nAccepte new client:%s:%d", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
			memset(c_Message,0,1024);//将原来的client message归零
			continue;
		}
		c_Message[ret] = '\0';
		printf("\nReceived: %s\n", c_Message); 
	}
	return 0; 
}<strong>
</strong>

Client:

#include <WINSOCK2.H> //套接字库
#include <stdio.h>

#define SERVER_ADDRESS "127.0.0.1" //服务器端IP地址,由于服务也在本地机器上所以用环回地址127.0.0.1

#define PORT           6000    //客户端绑定端口     
#define MSGSIZE        1024    	//客户端接收数据缓冲区大小    
#pragma comment(lib, "ws2_32.lib") 

DWORD WINAPI FunThread(LPVOID); //对于客户端接收数据的线程函数   

SOCKET      sClient;         //客户端套接字      
SOCKADDR_IN server;           //服务器端套接字

     
int main()
{ 
	WSADATA     wsaData; 
	char        c_Message[MSGSIZE]; //数据缓冲区
	
	WSAStartup(0x0202, &wsaData); //初始化套接字库
	
	sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    //创建客户端套接字
	
	memset(&server, 0, sizeof(SOCKADDR_IN));               //先将保存地址的server置为全0
	server.sin_family = PF_INET;                           //声明地址格式是TCP/IP地址格式
	server.sin_port = htons(PORT);                         //指明连接服务器的端口号
	server.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);    //指明连接服务器的IP地址
	

	connect(sClient, (struct sockaddr *)&server, sizeof(SOCKADDR_IN)); //连到刚才指明的服务器上

	HANDLE hThread=CreateThread(NULL,0,FunThread,0,0,0);;//客户端开辟接收数据线程
	CloseHandle(hThread);

	//客户端向服务器发送数据
	while (TRUE)
	{
		printf("Client Send:");
		gets(c_Message);   
		
		send(sClient, c_Message, strlen(c_Message), 0); 
		if(!strcmp(c_Message,"exit"))//client自身退出
			exit(1);
	}
	
	// 释放连接和进行结束工作
	closesocket(sClient);
	WSACleanup();
	return 0;
}

//接收线程函数
DWORD WINAPI FunThread(LPVOID)
{
	char   s_Message[MSGSIZE];//定义接收缓冲区
	int    ret; 
	while (TRUE)
	{
		ret = recv(sClient, s_Message, MSGSIZE, 0);//接收服务器端的数据
	

		//判断是否接收
		if(ret==SOCKET_ERROR)
		{
			printf("\nServer is closed!\n");
			exit(1);
		}
		s_Message[ret] = '\0';  
		//显示接收数据
		printf("\nReceived: %s\n", s_Message);
		
		//如果服务器端发送exit则client退出
		if(!strcmp(s_Message,"exit"))//server让client退出
			exit(1);
	}
	return 0;
}<strong>
</strong>


运行结果如下:


基于TCP套接字实现的简单Demo_第1张图片






后面的文章我将会介绍套接字的基础以及代码中涉及的CreateThread.


代码中难免BUG,望读者批评指正.




转载请注明作者:小刘


你可能感兴趣的:(线程,tcp,socket,套接字)