c 网络编程之TCP

简介

此项目的目的是分别编写TCP的客户端和服务端程序并为两者建立通信,客户端收到从服务端发送的服务端本地时间。

环境

此项目在Dev-C++ 5.11下开发,需要用到的库有winsock2.h,以及静态链接文件wsock32.lib。
需要分别创建两个项目server和client,先运行server.cpp,再运行client.cpp。

服务端程序

//server.cpp
#include<winsock2.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void errexit(const char*, ...);//错误信息打印函数
void TCPdaytimed(SOCKET);//将本地时间通过连接套接字发送
SOCKET passiveTCP(const char*, int);//创建服务端的监听套接字

#define QLEN 5 //客户端请求连接队列的最大长度
#define WSVERS MAKEWORD(2, 0)

int main(int argc, char* argv[]) {
    
    
	struct sockaddr_in fsin;
	const char* service = "daytime";//服务名称,在此程序中只作为参考不会被使用
	SOCKET msock, ssock;
	int alen;
	WSADATA wsadata;

	switch (argc) {
    
    
	case 1 :
		break;
	case 2:
		service = argv[1];
		break;
	default:
		errexit("usage: TCPdaytimed [port]\n");
	}

	if (WSAStartup(WSVERS, &wsadata) != 0) {
    
    
		errexit("WSAStartup failed\n");
	}
	msock = passiveTCP(service, QLEN);

	while (1) {
    
    
		alen = sizeof(struct sockaddr);
		ssock = accept(msock, (struct sockaddr*)  &fsin, &alen);
		if (ssock == INVALID_SOCKET) {
    
    
			errexit("accept failed: error number %d\n", GetLastError());
		}
		TCPdaytimed(ssock);
		(void)closesocket(ssock);
	}

	
}
void TCPdaytimed(SOCKET fd) {
    
    
	char* pts;
	time_t now;
	(void)time(&now);
	pts = ctime(&now);
	(void)send(fd, pts, strlen(pts), 0);
	printf("%s", pts);
}

SOCKET passiveTCP(const char* service, int qlen) {
    
    
	SOCKET sockfd;
	struct sockaddr_in sock_address;

	sockfd = socket(AF_INET, SOCK_STREAM, 0);  //获得fd
	sock_address.sin_family = AF_INET;  //设置地址家族
	sock_address.sin_port = htons(23456);  //设置端口
	sock_address.sin_addr.s_addr = inet_addr("127.0.0.1");  //设置地址
	int temp = bind(sockfd, (struct sockaddr*) & sock_address, sizeof(struct sockaddr));
	if (temp != 0) errexit("bind falied.\n");
	temp = listen(sockfd, qlen);
	if (temp != 0) errexit("listen falied.\n");
	return sockfd;
}

void errexit(const char *format, ...) {
    
    
	va_list args;

	va_start(args, format);
	vfprintf(stderr, format, args);
	va_end(args);
	WSACleanup();
	exit(1);

}

客户端程序

#include<winsock2.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void TCPdaytime(const char*, const char*); //主程序,从指定的服务器节点获取服务器的本地时间 
void errexit(const char*, ...);
SOCKET connectTCP(const char*, const char*);//被TCPdaytime调用,创建连接到服务器的套接字 

#define LINELEN 128
#define WSVERS MAKEWORD(2,0)

int main(int argc, char* argv[]) {
    
    
	const char * host = "127.0.0.1";
	const char* service = "daytime";
	WSADATA wsadata;

	switch (argc) {
    
    
	case 1:
		host = "localhost";
		break;
	case 3:
		service = argv[2];
	case 2:
		host = argv[1];
		break;
	default:
		fprintf(stderr, "usage: TCPdaytime [host [port]]\n");
		exit(1);
	}

	if (WSAStartup(WSVERS, &wsadata) != 0) {
    
    
		errexit("WSAStartup failed\n");

	}
	TCPdaytime(host, service);
	WSACleanup();
	printf("按任意键继续...");
	getchar();
	return 0;

}

void TCPdaytime(const char* host, const char* service) {
    
    
	char buf[LINELEN + 1];
	SOCKET s;
	int cc;
	s = connectTCP(host, service);

	cc = recv(s, buf, LINELEN, 0);
	while (cc != SOCKET_ERROR && cc > 0) {
    
    
		buf[cc] = '\0';
		(void)fputs(buf, stdout);
		cc = recv(s, buf, LINELEN, 0);
	}

	closesocket(s);

}

void errexit(const char* format, ...) {
    
    
	va_list args;

	va_start(args, format);
	vfprintf(stderr, format, args);
	va_end(args);
	WSACleanup();
	exit(1);

}


SOCKET connectTCP(const char* host, const char* service) {
    
    
	SOCKET sockfd;
	struct sockaddr_in mysock;

	sockfd = socket(AF_INET, SOCK_STREAM, 0);  //获得fd
	mysock.sin_family = AF_INET;  //设置地址家族
	mysock.sin_port = htons(23456);  //设置端口
	mysock.sin_addr.s_addr = inet_addr("127.0.0.1");  //设置地址
	connect(sockfd, (struct sockaddr*) & mysock, sizeof(struct sockaddr));
	return sockfd;
}

运行

首先运行TCPserver.exe,接着分别运行三次TCPclient.exe(每次运行相当于从服务器获取一次时间),执行结果如下:

客户端

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

服务端

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43867940/article/details/106402775