您的位置:首页 > 理论基础 > 计算机网络

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

2014-02-10 16:27 811 查看
代码来自书上,主要是了解过程。

服务器代码

// 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: 在此处引用程序需要的其他头文件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: