在客户端与服务端进行信息交互的时候,我们经常想让他们进行实时对话,下面我将给出客户端与服务器实时通信的代码,采用C语言与C++混合编写,基于tcp协议,键盘输入想发送的数据,接收到数据之后,对数据进行解析。老规矩,让我们开始初始化套接字。
一,初始化
1.初始化网络库
bool init_Socket()//初始化网络库
{
WSADATA wsadata;
if (0 != WSAStartup(MAKEWORD(2, 2), &wsadata))//windows异步套接字启动
{
printf("[error]WSAStarup failed,code %d\n", WSAGetLastError());
return false;
}
return true;
}
2.关闭网络库
bool close_Socket()//关闭网络库
{
if (0 != WSACleanup())
{
printf("[error]WSACleanup failed,code %d", WSAGetLastError());
return false;
}
return true;
}
3.创建套接字
以下代码为服务器创建套接字的过程,绑定套接字后需要有一个listen函数来监听我们的客户端是否有请求发到服务器。
SOCKET create_serverSocket()
{
SOCKET fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//创建一个空的socket
if (INVALID_SOCKET == fd)
{
printf("[error]socket failed,code %d", WSAGetLastError());
return INVALID_SOCKET;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);//把本地字节序转换为网络字节序
addr.sin_addr.S_un.S_addr = ADDR_ANY;//绑定本地任意IP
if (SOCKET_ERROR == bind(fd, (struct sockaddr*)&addr, sizeof(addr)))
{
printf("[error]bind failed,code %d", WSAGetLastError());
return INVALID_SOCKET;//-1
}
listen(fd, 10);
return fd;
}
以下代码为客户端创建套接字的过程,不需要绑定bind()函数,也不需要监听。
SOCKET create_clientSocket(const char* ip)
{
SOCKET fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//创建一个空的socket
if (INVALID_SOCKET == fd)
{
err("socket");
return INVALID_SOCKET;
}
//给socket绑定服务端的ip地址和端口号
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);//把本地字节序转换为网络字节序
addr.sin_addr.S_un.S_addr = inet_addr(ip);//绑定服务器任意IP
if (INVALID_SOCKET == connect(fd, (struct sockaddr*)&addr, sizeof(addr)))
{
err("connec");
return INVALID_SOCKET;
}
cout << "服务器连接成功!" << endl;
return fd;
}
二,实时通信
1.server端
在main函数中, 新建一个套接字clifd来发送数据,注意在send函数中填入的套接字是接收连接时accept新建的,而不是初始化用到那个套接字serfd,server端先接收客户端发来的消息,再对消息进行回应,运行程序时,自己在输出框填入想发送的数据即可。
int main()
{
int send_len ;
int recv_len ;//定义长度变量
int len ;
char send_buf[100] = { '\0' };
char recv_buf[100] = { '\0' };//定义发送缓冲区和接受缓冲区
init_Socket();
SOCKET serfd = create_serverSocket();
printf("服务端创建成功,等待客户端连接\n ");
SOCKET clifd = accept(serfd, NULL, NULL);//s_accept = accept(s_server, (SOCKADDR*)&accept_addr, &len);
while (true)
{
if (clifd == INVALID_SOCKET)
{
printf("[error]accept failed,code %d", WSAGetLastError());
closesocket(clifd);
closesocket(serfd);
close_Socket();
return 0;
}
printf("客户端连接成功\n");
while (true)
{
if (SOCKET_ERROR == recv(clifd, recv_buf, sizeof(recv_buf), 0))//recv_len = recv(s_accept, recv_buf, 100, 0);
{
printf("[error] failed,code %d", WSAGetLastError());
}
else
{
printf("客户端信息:%s\n", recv_buf);
}
if (strcmp(recv_buf, "bye") == 0)
{ //断开通信
cout << "本次通信结束!" << endl;
break;
}
cout << "请输入回复信息:\0";
cin >> send_buf;
send_len = send(clifd, send_buf, sizeof(send_buf), 0);
if (send_len < 0)
{
cout << "发送失败!" << endl;
break;
}
}
break;
}
closesocket(clifd);
closesocket(serfd);
close_Socket();
return 0;
}
2.cilent端
在main函数中,我们先发送消息到服务器,因为实际的项目中,基本上都是客户端先向服务器发送请求,然后再开始接收消息,当客户端发出“bye”时,我们的通信就结束了
int main()
{
//定义长度变量
int send_len = 0;
int recv_len = 0;
//定义发送缓冲区和接受缓冲区
char send_buf[100] = { '\0' };
char recv_buf[100] = { '\0' };
init_Socket();
SOCKET s_server = create_clientSocket("127.0.0.1");
while (true)
{
cout << "请输入发送信息:\0";
cin >> send_buf;
send_len = send(s_server, send_buf, sizeof(send_buf), 0);
if (send_len < 0)
{
cout << "发送失败!" << endl;
break;
}
if (strcmp(send_buf, "bye") == 0)
{ //输入bye就断开通信
cout << "本次通信结束!" << endl;
break;
}
recv_len = recv(s_server, recv_buf, sizeof(recv_buf), 0);
if (recv_len < 0)
{
cout << "接受失败!" << endl;
break;
} else
{
printf("服务器端信息:%s\n", recv_buf);
}
}
closesocket(s_server);
return 0;
}
以下是运行结果,然后给出完整代码下载链接: