当前位置 博文首页 > nandejxy的博客:C++ socket编程 实现服务端与客户端的双向TCP通
运行环境:VS2015
基于https://blog.csdn.net/orange_xxx/article/details/7276868做出了简单修改,可以完全实现双向的数据通信;
【来自https://blog.csdn.net/u012801153/article/details/79363575】
Server步骤:
Client步骤:
#include "winsock2.h"
#include <WS2tcpip.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib") // load the dll of winsock
using namespace std;
int main(int argc, char* argv[])
{
const int BUF_SIZE = 64;
WSADATA wsd; //WSADATA PARAM
SOCKET sServer; //Server Socket
SOCKET sClient; //Client Socket
SOCKADDR_IN servAddr; //Server Addr
SOCKADDR_IN clientAddr; //Client Addr
SOCKADDR_IN connect_Addr; //the Addr that connect this socket (in this demo, connect_Addr = clientAddr)
int connectClientlen = sizeof(connect_Addr);
char bufSend[BUF_SIZE]; //the buffer area of data-send
char bufRecv[BUF_SIZE]; //the buffer area of data-recv
int retVal; //return value
char* closeSymbol = "0"; //symbol of closing communication
char* bufReq = "Request Reply"; // symbol of Request Reply
char str[INET_ADDRSTRLEN];
// Server Addr
servAddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", (void*)&servAddr.sin_addr.S_un.S_addr);
servAddr.sin_port = htons((short)5000);
// Client Addr
clientAddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", (void*)&clientAddr.sin_addr.S_un.S_addr);
clientAddr.sin_port = htons((short)4999);
// Initialize the dll of winsock
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
{
cout << "WSAStartup failed !" << endl;
return 1;
}
// Create the Server socket
sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sServer)
{
cout << "socket failed!" << endl;
WSACleanup();
return -1;
}
else
{
cout << "Server TCP Socket init!" << endl;
}
// Bind the IP and Port on Server Socket
retVal = bind(sServer, (LPSOCKADDR)&servAddr, sizeof(SOCKADDR_IN));
if (SOCKET_ERROR == retVal)
{
cout << "bind failed!" << endl;
closesocket(sServer);
WSACleanup();
Sleep(5000);
return -1;
}
else
{
cout << "Server TCP Socket bind IP & Port !" << endl;
cout << "Server Address = " << inet_ntop(AF_INET, &servAddr.sin_addr, str, sizeof(str)) << ":" << ntohs(servAddr.sin_port) << endl;
}
// Listen the Server socket
retVal = listen(sServer, 10);
if (0 == retVal)
{
cout << "Server Socket is listening !" << endl;
}
else if (SOCKET_ERROR == retVal)
{
cout << "listen failed!" << endl;
closesocket(sServer);
WSACleanup();
Sleep(5000);
return -1;
}
cout << "Server Socket is waiting accpetion !" << endl;
sClient = accept(sServer, (sockaddr FAR*)&connect_Addr, &connectClientlen);
if (INVALID_SOCKET == sClient)
{
cout << "accept failed!" << endl;
closesocket(sServer);
WSACleanup();
Sleep(5000);
return -1;
}
else
{
cout << "Server get connection with client socket: [" << inet_ntop(AF_INET, &connect_Addr.sin_addr, str, sizeof(str)) << ":" << ntohs(connect_Addr.sin_port) << "]" << endl;
}
// loop for the data from the accpeted socket/send the data to the socket
while (TRUE)
{
// Initialize the buffer
ZeroMemory(bufRecv, BUF_SIZE);
// Recevice the buffer data from the client
retVal = recv(sClient, bufRecv, BUF_SIZE, 0);
if (SOCKET_ERROR == retVal)
{
continue;
}
// Check the data from client
bufRecv[retVal] = '\0'; // Set the last bit as \0 to avoid the wrong data
cout << "Data recv from Client Socket [" << inet_ntop(AF_INET, &connect_Addr.sin_addr, str, sizeof(str)) << ":" << ntohs(connect_Addr.sin_port) << "] : " << bufRecv << endl;
// When the data from client is ‘0’,exit the loop and finish TCP Communication
if (!strcmp(bufRecv, closeSymbol))
{
cout << "Client Socket wants to finish this communication" << endl;
closesocket(sServer);
WSACleanup();
Sleep(5000);
break;
}
else
{
// Automatically send the request reply to client
send(sClient, bufReq, strlen(bufReq), 0);
}
}
// Exit
closesocket(sServer);
WSACleanup();
Sleep(5000);
return 0;
}
// Client.cpp : Defines the entry point for the console application.
#include "winsock2.h"
#include <WS2tcpip.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
using namespace std;
int main(int argc, char* argv[])
{
const int BUF_SIZE = 64;
WSADATA wsd; //WSADATA Param
SOCKET sClient; //Server Socket
SOCKADDR_IN servAddr; //Server Addr
SOCKADDR_IN clientAddr; //Client Addr
SOCKADDR_IN send_Data_Addr; //the Addr that send the data(in this demo, send_Data_Addr = servAddr)
int nAddrLen = sizeof(clientAddr);
int nAddrLen_s = sizeof(servAddr);
char bufSend[BUF_SIZE]; //the buffer area of data-send
char bufRecv[BUF_SIZE]; //the buffer area of data-recv
int retVal; //return value
char* closeSymbol = "0"; //symbol of close
// Server Addr
servAddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", (void*)&servAddr.sin_addr.S_un.S_addr);
servAddr.sin_port = htons((short)5000);
int nServAddlen = sizeof(servAddr);
// Client Addr
clientAddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", (void*)&clientAddr.sin_addr.S_un.S_addr);
clientAddr.sin_port = htons((short)4999);
int nClientAddlen = sizeof(clientAddr);
// Initialize the dll of winsock
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
{
cout << "WSAStartup failed!" << endl;
return -1;
}
// Create the Server socket
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sClient)
{
cout << "Socket failed !" << endl;
WSACleanup();
Sleep(5000);
return -1;
}
else
{
cout << "Client Socket init !" << endl;
}
// Bind the client socket with IP and Port
retVal = bind(sClient, (LPSOCKADDR)&clientAddr, sizeof(SOCKADDR_IN));
if (SOCKET_ERROR == retVal)
{
cout << "bind failed!" << endl;
closesocket(sClient);
WSACleanup();
Sleep(5000);
return -1;
}
else
{
cout << "Client UDP Socket bind IP & Port !" << endl;
char str[INET_ADDRSTRLEN];
cout << "Client Address = " << inet_ntop(AF_INET, &clientAddr.sin_addr, str, sizeof(str)) << ":" << ntohs(clientAddr.sin_port) << endl;
}
// client request connect server socket
retVal = connect(sClient, (LPSOCKADDR)&servAddr, sizeof(servAddr));
if (SOCKET_ERROR == retVal)
{
cout << "Client connect failed!" << endl;
closesocket(sClient);
WSACleanup();
Sleep(5000);
return -1;
}
else
{
cout << "Client connect with Server socket" << endl;
}
// loop for the data from the connected socket/send the data to the server socket
while (true) {
// Initialize the buffer
ZeroMemory(bufSend, BUF_SIZE);
// Send the data from client socket to Server Socket
cout << "Data send to Server Socket: ";
cin >> bufSend;
retVal = send(sClient, bufSend, strlen(bufSend), 0);
if (SOCKET_ERROR == retVal)
{
cout << "Send failed!" << endl;
closesocket(sClient);
WSACleanup();
Sleep(5000);
return -1;
}
// When the data from another socket is ‘0’,exit the loop and finish TCP Communication
if (!strcmp(bufSend, closeSymbol))
{
cout << "Client Socket wants to finish this communication" << endl;
break;
}
// Receive data from server socket
retVal = recv(sClient, bufRecv, BUF_SIZE, 0);
bufRecv[retVal] = '\0';
cout << "Data recv from Server Socket: " << bufRecv << endl;
}
closesocket(sClient);
WSACleanup();
Sleep(5000);
return 0;
}
?
inet_pton(AF_INET, "127.0.0.1", (void*)&servAddr.sin_addr.S_un.S_addr);这句话是替代了inet_addr的作用,vs2015里面inet_addr好像不能用了,只能用inet_pton替代,之前需要添加#include <WS2tcpip.h>。这里是单机内两个进程间的通信,最后采用的是127.0.0.1的localhost作为IP地址。
WSAStartup(MAKEWORD(2,2),&wsaData):其中MAKEWORD(2,2)表示使用WINSOCK2版本,wsaData用来存储系统传回的关于WINSOCK的资料;
ZeroMemory(bufSend, BUF_SIZE);? ?//端口发送数据,需要在每次交互前,把之前的buf数据清空,避免缓冲区冗余;但是不能对这个端口的接受数据的缓冲bufRecv清空;这样会造成永久性的空接受情况。
retVal = recv(sClient, bufRecv,BUF_SIZE , 0);? ?//端口接受另一个端口数据,字符位要选择允许的满字符,这里为BUF_SIZE,确保每次都能把另一个端口的数据全都接收到;其中retVal记录了这组数据的长度;
这里需要注意,不论是客户端还是服务端,recv和send的第一个参数都是sClient,即客户端的socket,即在TCP通信中recv和send函数的第一个参数应该是发起connect连接的socket。
bufRecv[retVal] = '\0';? //每次接受到的数据因为没有初始化,初始结构都是“烫烫烫烫”,在接受到后,会把前面的若干位变成接受的数据,但是后面还是都为烫,因此需要这个语句将接受数据的缓冲收尾,接受有效的前面若干位数据,剔除烫烫烫烫。
最后通过输入0来结束本次通信,若客户端发送了一个"0",那就表示需要结束本次通信,两个进程会在5秒内自动关闭。
两个代码分别放于两个项目中,先运行启动服务端代码,然后运行客户端代码,就可以进行本机的两端通信调试。若先启动了客户端,由于代码保护,一旦客户端无法找到可以连接的服务端,客户端会马上关闭;而先打开服务端的话,服务端会一直处于等待连接状态。
深圳SEO优化公司沙井seo优化南山关键词按天计费丹竹头关键词按天收费木棉湾百姓网标王民治百度关键词包年推广横岗设计公司网站民治网站优化排名双龙网站排名优化平湖百度竞价包年推广横岗外贸网站建设坪地百姓网标王推广光明百度seo平湖网站推广工具吉祥阿里店铺托管坪山阿里店铺托管深圳网络营销吉祥网站搜索优化木棉湾百度标王沙井百度标王坪地品牌网站设计坑梓网站推广方案布吉网站改版深圳百姓网标王推广福永网站优化按天收费布吉百度标王平湖百姓网标王推广福田百姓网标王吉祥网站推广工具南联百度竞价福永设计网站歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运