流式套接字C/S通信程序

客户端

#include"stdafx.h"
#define WIN32_LEAN_AND_MEAN
#include<Windows.h>
#include<WinSock2.h>
#include<WS2tcpip.h>
#include<stdlib.h>
#include<stdio.h>

//连接到winsock2对应的lib文件:ws2_32.lib,Mswsock.lib,Advapi32.lib
#pragma comment (lib,"Ws2_32.lib")
#pragma comment (lib,"Mswsock.lib")
#pragma comment (lib,"AdvApi32.lib")

//定义默认的缓冲区长度和端口号
#define DEFAULT_BUFLEN 512  
#define DEFAULT_PORT "27015" 


int _cdecl main(int argc, char** argv)
{

	WSADATA wsadata;
	SOCKET Connectsocket = INVALID_SOCKET;
	struct addrinfo * result = NULL,*ptr = NULL,hints;
	char *sendbuf = "bryant_xw";
	char recvbuf[DEFAULT_BUFLEN]; 
	
	int iResult;
	int recvbuflen = DEFAULT_BUFLEN;

	//验证参数的合法性
	if(argc != 2)
	{
		printf("usage:%s server-name\n",argv[0]);
		return 1;
	}

	//初始化套接字
	iResult = WSAStartup(MAKEWORD(2,2),&wsadata);
	if(iResult != 0)
	{
		printf("WSAStartup failed with error %d\n",iResult);
		return 1;
	}
	ZeroMemory(&hints,sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	//解析服务器的地址和端口
	iResult = getaddrinfo(argv[1],DEFAULT_PORT,&hints,&result); //成功返回的是0
	if(iResult != 0)
	{
		printf("GetAddrInfo is failed with error %d\n",iResult);
		WSACleanup();
		return 1;
	}

	//尝试连接服务器地址,直到成功
	for(ptr = result; ptr!=NULL;ptr = ptr->ai_next)
	{
		//创建套接字
		Connectsocket = socket(ptr->ai_family,ptr->ai_socktype,ptr->ai_protocol);
		if(Connectsocket == INVALID_SOCKET)
		{
			printf("socket failed with error %ld\n",WSAGetLastError());
			WSACleanup();
			return 1;
		}
		//向服务器发起连接
		iResult = connect(Connectsocket,ptr->ai_addr,(int)ptr->ai_addrlen);
		if(iResult == SOCKET_ERROR)
		{
			closesocket(Connectsocket);
			Connectsocket = INVALID_SOCKET;
			continue;
		}
		break;
	}
	freeaddrinfo(result);

	if(Connectsocket == INVALID_SOCKET)
	{
		printf("unable to connect to server");
		WSACleanup();
		return 1;
	}
	//发送缓冲区的测试数据
	iResult = send(Connectsocket,sendbuf,(int)strlen(sendbuf),0);
	if(iResult ==  SOCKET_ERROR)
	{
		printf("send failed with error %ld\n",WSAGetLastError());
		closesocket(Connectsocket);
		WSACleanup();
		return 1;
	}
	printf("Bytes sent :%ld\n",iResult);

	//数据发送结束,调用shutdown函数声明不再发送数据,但是此时客户端人可以接收数据
	iResult = shutdown(Connectsocket,SD_SEND);
	if(iResult ==  SOCKET_ERROR)
	{
		printf("shutdown failed with error %ld\n",WSAGetLastError());
		closesocket(Connectsocket);
		WSACleanup();
		return 1;
	}

	//持续接收数据,直到服务器关闭连接
	do
	{
		iResult = recv(Connectsocket,recvbuf,recvbuflen,0);
		if(iResult > 0)
			printf("Bytes recevied: %d\n",iResult);
		else if(iResult == 0)
			printf("Connection closed\n");
		else
			printf("recv failed with error: %d\n",WSAGetLastError());
	} while (iResult > 0);
	
	//关闭套接字
	closesocket(Connectsocket);
	//释放资源
	WSACleanup();
	return 0;
}

服务器端

#include"stdafx.h"
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include<Windows.h>
#include<WinSock2.h>
#include<WS2tcpip.h>
#include<stdlib.h>
#include<stdio.h>

#pragma comment(lib,"Ws2_32.lib")//连接到Winsock 2 对应的lib文件:ws2_32.lib

//定义默认的缓冲区长度和端口号
#define DEFAULT_BUFLEN 512  
#define DEFAULT_PORT "27015" 


int _cdecl main(void)
{
	WSADATA wsadata;
	int iResult;
	SOCKET ListenSocket = INVALID_SOCKET;
	SOCKET ClientSocket = INVALID_SOCKET;
	struct addrinfo *result = NULL;
	struct addrinfo hints;

	int iSentResult;
	char recvbuf[DEFAULT_BUFLEN];
	int recvbuflen = DEFAULT_BUFLEN;
	
	//初始化winsock
	iResult = WSAStartup(MAKEWORD(2,2),&wsadata);
	if(iResult != 0)
	{
		printf("WSAStartup failed with error:%d\n",iResult);
		return 1;
	}

	ZeroMemory(&hints,sizeof(hints));

	//声明IPv4地址族,流式套接字,TCP协议
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE;
	
	//解析服务器地址和端口号
	iResult = getaddrinfo(NULL,DEFAULT_PORT,&hints,&result); //成功返回的是0
	if(iResult != 0)
	{
		printf("getaddrinfo is failed with error %d\n",iResult);
		return 1;
	}

	//调用socket函数创建一个流式套接字
	ListenSocket = socket(result->ai_family,result->ai_socktype,result->ai_protocol);
	if(ListenSocket == INVALID_SOCKET)
	{
		printf("socket failed with error %ld\n",WSAGetLastError());
		free(result);
		WSACleanup();
		return 1;
	}

	//为套接字绑定地址和端口号
	iResult = bind(ListenSocket,result->ai_addr,(int)result->ai_addrlen); //成功返回0
	if(iResult != 0)
	{
		printf("bind failed with error %d\n",WSAGetLastError());
		freeaddrinfo(result);
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}
	freeaddrinfo(result);

	//监听连接请求

	iResult  = listen(ListenSocket,SOMAXCONN);//成功返回0

	if(iResult != 0)
	{
		printf("listen failed with error %d\n",WSAGetLastError()); //
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}

	//接收客户端的连接请求,返回  新的  连接套接字 ClientSocket ,之后在ClientSocket上读写
	ClientSocket = accept(ListenSocket,NULL,NULL);  
	if(ClientSocket == INVALID_SOCKET)
	{
		printf("accept failed with error %d\n",WSAGetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}	

	
	//持续接收数据直到对方关链接
	do
	{
		iResult = recv(ClientSocket,recvbuf,recvbuflen,0);
		//case 1:成功接收数据
		if(iResult > 0)
		{
			printf("Bytes received:%d\n",iResult);
			
			//将缓冲区的内容回送给客户端
			iSentResult = send(ClientSocket,recvbuf,iResult,0);
			if(iSentResult == SOCKET_ERROR)
			{
				printf("send failed with error %d\n",WSAGetLastError());
				closesocket(ClientSocket);
				WSACleanup();
				return 1;
			}
			printf("Bytes sent: %d\n",iSentResult);
		}

		//case 2: 连接关闭
		else if(iResult == 0)
		{
			printf("Connection closing..\n");
		}
		//case3: 接收发生错误
		else 
		{
			printf("recv failed with error %d\n",WSAGetLastError());
			closesocket(ClientSocket);
			WSACleanup();
			return 1;
		}

	} while (iResult > 0);

	//关闭连接
	iResult = shutdown(ClientSocket,SD_SEND);
	if(iResult != 0)
	{
		printf("shutdown failed with error %d\n",WSAGetLastError());
		closesocket(ClientSocket);
		WSACleanup();
		return 1;
	}
	//关闭套接字,释放资源
	closesocket(ClientSocket);
	WSACleanup();
	//在必须要监听的套接字的情况下释放该套接字
	closesocket(ListenSocket);
	
	return 0;
}

运行的结果如下图:
字符串的初始值是bryant_xw即9个字符

猜你喜欢

转载自blog.csdn.net/bryant_xw/article/details/82916292