一个简单的TCP服务器与客户端示例

代码来自书上,主要是了解过程。



服务器代码

// P97_TcpServer.cpp : 定义控制台应用程序的入口点。
//

/**
 * wsa2库, creat socket, set addr, bind, listen, accept request, 
 * 
 **/

#include "stdafx.h"
//#include <WinSock2.h>
//#include <Windows.h>

//#pragma comment (lib, "WS2_32.lib")

#define BUF_SIZE 64

int _tmain(int argc, _TCHAR* argv[])
{
	WSADATA wsaData;
	SOCKET listenSock;
	SOCKET acceptSock;
	char Serverbuf[BUF_SIZE];

	// 初始化Socket动态库
	if ( WSAStartup(MAKEWORD(2,2), &wsaData) != 0){
		printf("WSAStartup falid.\n");
		WSACleanup();
		exit(1);
	}

	// 创建Socket
	if ((listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET){
		printf("Creat listenSock failed\n");
		WSACleanup();
		exit(1);
	}

	// 设置服务器地址信息
	SOCKADDR_IN addrServ;
	addrServ.sin_family = AF_INET;
	addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addrServ.sin_port = htons(9990);

	// 绑定套接字与端口
	if (bind(listenSock, (sockaddr*) &addrServ, sizeof(addrServ)) == SOCKET_ERROR){
		printf("bind faild\n");
		closesocket(listenSock);
		WSACleanup();
		exit(1);
	}

	// 监听套接字
	if (listen(listenSock, 5) == SOCKET_ERROR){
		printf("listen faild\n");
		closesocket(listenSock);
		WSACleanup();
		exit(1);
	}

	// 接受客户端连接
	// 需要保存客户端地址信息
	printf("Tcp Server start...\n\n");
	SOCKADDR_IN addrClient;
	int addrClientLen = sizeof(addrClient);
	if ((acceptSock = accept(listenSock, (sockaddr*)&addrClient, &addrClientLen)) == INVALID_SOCKET){
		printf("accept listenSock failed\n");
		closesocket(listenSock);
		closesocket(acceptSock);
		WSACleanup();
		exit(1);
	}

	// 循环接受客户端数据,直到收到quit命令
	while (true){
		ZeroMemory(Serverbuf, BUF_SIZE);// 清空缓冲区
		if ( recv(acceptSock, Serverbuf, BUF_SIZE, 0) == SOCKET_ERROR){
			printf("recv failed.\n");
			closesocket(listenSock);
			closesocket(acceptSock);
			WSACleanup();
			exit(1);
		}
		
		SYSTEMTIME st;
		GetLocalTime(&st);
		char sDateTime[30];
		sprintf (sDateTime,
			"%4d-%2d-%2d %2d:%2d:%2d", 
			st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
		printf("%s :%s\n", sDateTime, Serverbuf);
		
		// if content is "quit", then Server quit.
		if (strcmp(Serverbuf, "quit") == 0){
			if (send(acceptSock , "quit", strlen("quit"), 0) == SOCKET_ERROR){
				printf("send \"quit\" failed\n");
			}
			break;
		}
		// or, send the same msg
		else{
			char msg[BUF_SIZE];
			sprintf(msg, "Message recevied: %s\n", Serverbuf);
			if (send(acceptSock, Serverbuf, BUF_SIZE, 0) == SOCKET_ERROR){
				printf("Send failed!\n");
				closesocket(listenSock);
				closesocket(acceptSock);
				WSACleanup();
				exit(1);
			}

		}// end of if-else
	}// end of while

	// release all resource
	closesocket(listenSock);
	closesocket(acceptSock);
	WSACleanup();

	system("pause");
	return 0;
}


// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//

#pragma once

#include "targetver.h"

#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <WinSock2.h>
#include <Windows.h>

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



// TODO: 在此处引用程序需要的其他头文件


客户端代码

// P100_TcpClient.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#define BUF_SIZE 64


int _tmain(int argc, _TCHAR* argv[])
{
	WSADATA wsaData;
	SOCKET sHost;
	SOCKADDR_IN servAddr;	//	服务器IP
	char buf[BUF_SIZE];

	// 初始化Socket库
	if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0){
		printf("WSAStartup failed!\n");
		WSACleanup();
		exit(1);
	}

	// 创建Socket
	if ((sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET){
		printf("socket failed!\n");
		WSACleanup();
		exit(1);
	}

	// 设置服务器地址
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	// 假设的服务器地址,实际应用中服务器地址和端口号应该保存在配置文件中
	servAddr.sin_port = htons(9990);
	int sServAddrLen = sizeof(servAddr);

	// link to server
	if (connect(sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr)) == SOCKET_ERROR){
		printf("connect failed!\n");
		printf("%d\n", WSAGetLastError());
		closesocket(sHost);
		WSACleanup();
		exit(1);
	}

	// 循环向服务器发送数据
	// quit命令退出与服务器连接,之后客户端自身退出
	printf("已连接至服务器...\n\n");
	while(true){
		printf("Send: ");
		std::string str;
		std::getline(std::cin, str);	// 从标准输入流中读取一行
		ZeroMemory(buf, BUF_SIZE);
		strcpy(buf,str.c_str());	// c_str()把字符串转为数组中存放的形式
		if (send(sHost, buf, strlen(buf), 0) == SOCKET_ERROR){
			printf("send failed!\n");
			closesocket(sHost);
			WSACleanup();
			exit(1);
		}

		// 接受服务器传回的消息
		if (recv(sHost, buf, sizeof(buf)+1, 0) == SOCKET_ERROR){
			printf("recv failed!\n");
			closesocket(sHost);
			WSACleanup();
			exit(1);
		}

		printf("Recv: %s\n", buf);
		// 若收到quit,则退出
		if (strcmp(buf, "quit") == 0){
			printf("quit!\n");
			break;
		}
	}// end of while

	// release all resource
	closesocket(sHost);
	WSACleanup();

	system("pause");
	return 0;
}


// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//

#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>

#include <WinSock2.h>
#include <iostream>
#include <string>

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



// TODO: 在此处引用程序需要的其他头文件




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值