windows网络编程-C语言实现简单的TCP协议聊天
TCP/IP协议(面向连接协议)类似于打电话时,对方一定在手机附近并且此刻都在和对方进行通话。一定保证双方都在线,才能进行数据传输。UDP/IP协议(无连接协议)就像邮箱,不保证对方一定在等你邮件且对方不在你也可以给对方发送数据。实际上TCP协议、UDP协议,还有重要的TCP协议中的三次握手(建立连接)和四次挥手(关闭连接)等在网上也都解释得非常详细了,所以我就不多说了。
Server端程序代码:
/*
* 服务器端 Server.c
*
*/
#include <winsock2.h>
#include <stdio.h>
#include <string.h> #define BUFFSIZE 1024 int main(int argc, char**argv)
{
int Ret;
WSADATA wsaData;
SOCKET ListeningSocket;
SOCKET NewConnection;
SOCKADDR_IN ServerAddr;
SOCKADDR_IN ClientAddr;
int ClientAddrLen = sizeof(ClientAddr);
unsigned short Port = 5150;
char sendData[BUFFSIZE];
char recvData[BUFFSIZE]; if((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
{
printf("WSASTARTUP_ERROR: %d\n", Ret);
return 0;
} //创建一个套接字来监听客户机连接
if((ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("SOCKET_ERROR: %d\n", INVALID_SOCKET);
return 0;
} /*
* 填充SOCKADDR_IN结构,这个结构将告知bind我们想要在5150端口监听所有接口上的连接
*/
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(Port); //将端口变量从主机字节顺序转换位网络字节顺序
ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //使用bind将这个地址信息和套接字绑定起来
if(bind(ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR)
{
printf("BIND_ERROR: %d\n", SOCKET_ERROR);
return 0;
} //监听客户机连接。这里使用5个backlog
if(listen(ListeningSocket, 5) == SOCKET_ERROR)
{
printf("LISTEN_ERROR: %d\n", SOCKET_ERROR);
return 0;
} //连接到达时,接受连接
printf("正在接受连接...");
if((NewConnection = accept(ListeningSocket, (SOCKADDR *)&ClientAddr, &ClientAddrLen)) == INVALID_SOCKET)
{
printf("ACCPET_ERROR: %d\n", INVALID_SOCKET);
closesocket(ListeningSocket);
return 0;
}
printf("检测到一个连接: %s 端口:%d\n", inet_ntoa(ClientAddr.sin_addr), ntohs(ClientAddr.sin_port)); //聊天
while(true)
{
//接收数据
Ret = recv(NewConnection, recvData, BUFFSIZE, 0);
if(Ret > 0)
printf("C.C.: %s\n", recvData);
else if(Ret < 0)
printf("RECV_ERROR: %d\n", SOCKET_ERROR);
else
{
printf("对方退出程序,聊天结束!");
break;
} //发送数据
printf("\n鲁鲁:");
scanf("%s", sendData);
if(strcmp(sendData, "quit") == 0) //退出
break;
if(send(NewConnection, sendData, BUFFSIZE, 0) == SOCKET_ERROR)
{
printf("消息发送失败!\n");
break;
}
}
//从容关闭
shutdown(NewConnection, SD_BOTH); //完成新接受的连接后,用closesocket API关闭这些套接字
closesocket(NewConnection);
closesocket(ListeningSocket); //应用程序完成对接的处理后,调用WSACleanup
if(WSACleanup() == SOCKET_ERROR)
{
printf("WSACLEANUP_ERROR: %d\n", WSAGetLastError());
return 0;
} system("pause");
return 0;
}
Client端程序代码:
/*
* 客户端 Client.c
*
*/
#include <winsock2.h>
#include <stdio.h>
#include <string.h> #define BUFFSIZE 1024 int main(int argc, char**argv)
{
int Ret;
WSADATA wsaData;
SOCKET s;
SOCKADDR_IN ServerAddr;
unsigned short Port = 5150;
char sendData[BUFFSIZE];
char recvData[BUFFSIZE]; if((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
{
printf("WSASTARTUP_ERROR: %d\n", Ret);
return 0;
} if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("SOCKET_ERROR: %d\n", INVALID_SOCKET);
return 0;
} ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(Port);
ServerAddr.sin_addr.S_un.S_addr = inet_addr("192.168.1.101");// 这里S_un.S_addr在不同的IDE中可能不一样,然后IPv4地址使用该程序所运行在的PC上的IPv4地址 if((connect(s, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr))) == SOCKET_ERROR)
{
printf("CONNECT_ERROR: %d\n", SOCKET_ERROR);
closesocket(s);
return 0;
} //Chat
while(true)
{
printf("\nC.C:");
scanf("%s", sendData);
if(strcmp(sendData, "quit") == 0) //quit
break;
if(send(s, sendData, BUFFSIZE, 0) == SOCKET_ERROR)
{
printf("消息发送失败!\n");
break;
} Ret = recv(s, recvData, BUFFSIZE, 0);
if(Ret > 0)
printf("鲁鲁: %s\n", recvData);
else if(Ret < 0)
printf("RECV_ERROR: %d\n", SOCKET_ERROR);
else
{
printf("对方退出程序,聊天结束!");
break;
}
}
shutdown(s, SD_BOTH);
closesocket(s); if(WSACleanup() == SOCKET_ERROR)
{
printf("WSACLEANUP_ERROR: %d\n", WSAGetLastError());
return 0;
} system("pause");
return 0;
}
运行结果:

对于所有可能出现的错误我都加上了会出错的函数名前缀,以便于定位出现错误的位置。
其他的书上解释得很详细,就不暴露自己水平了233...
p.s.2018-05-13 15:10:46
AF_INET的原型是:
#define AF_INET 2
然后关于客户端代码中的inet_addr()可看一下我的这篇,其中有一段相关解释。
windows网络编程-C语言实现简单的TCP协议聊天的更多相关文章
- windows网络编程-C语言实现简单的UDP协议聊天
与TCP协议下编写服务端程序代码类似,但因为是无连接的形式,所以不需要监听. 这次,我用了一点不同的想法:我建立一个服务端,用了两个端口和两个套接字,把服务端作为一个数据转发的中转站,使得客户机之间进 ...
- linux 网络编程:客户端与服务器通过TCP协议相互通信 + UDP
1.TCP编程的客户端一般步骤: 1.创建一个socket,用函数socket(): 2.设置socket属性,用函数setsockopt():* 可选: 3.绑定IP地址.端口等信息到socket上 ...
- {网络编程}和{多线程}应用:基于TCP协议【实现多个客户端发送文件给一个服务器端】--练习
要求: 实现多个客户端发送文件给一个服务器端 提示:多个人创建客户端发送文件,服务端循环接收socket,从socket中获取文件 说明:这里我们只要建立一个服务端就可以了,然后让多台电脑使用客户端给 ...
- [转]Windows网络编程学习-面向连接的编程方式
直接附上原文链接:windows 网络编程学习-面向连接的编程方式
- Windows网络编程 2 【转】
Windows网络编程使用winsock.Winsock是一个基于Socket模型的API,在Windows系统中广泛使用.使用Winsock进行网络编程需要包含头文件Winsock2.h,需要使用库 ...
- 【Hadoop离线基础总结】zookeeper的介绍以及集群环境搭建、网络编程和RPC的简单了解
ZooKeeper的介绍以及集群环境搭建.网络编程和RPC的简单了解 ZooKeeper介绍 概述 ZooKeeper是一个分布式协调服务的开源框架,主要用来解决分布式集群中应用系统的一致性问题.例如 ...
- Android网络编程要学的东西与Http协议学习
本节引言: 本节开始我们来学习Android网络编程相关的一些东西:Android端网络编程是要干嘛?http协议的学习,使用自带扣脚Json解析类解析Json,XML解析常用的几种方式,HttpUr ...
- Python网络编程03 /缓存区、基于TCP的socket循环通信、执行远程命令、socketserver通信
Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命令.socketserver通信 目录 Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命 ...
- 网游中的网络编程系列1:UDP vs. TCP
原文:UDP vs. TCP,作者是Glenn Fiedler,专注于游戏网络编程相关工作多年. 目录 网游中的网络编程系列1:UDP vs. TCP 网游中的网络编程2:发送和接收数据包 网游中的网 ...
随机推荐
- noobSTL-0-开题报告
noobSTL-0-开题报告 STL介绍 STL是Standard Template Library的简称,中文名标准模板库. STL是一种泛型编程.面向对象编程关注的是编程的数据方面,而泛型编程关注 ...
- 安装Oracle进行先决条件检查时显示 Environment variable:"PATH" 失败”
问题已解决:安装时exe可执行文件的目录也不能有中文,安装时注意目录一定要按oracle的格式.运行安装程序时,要用右键--> 要以管理员方式启动. 原文: 用到oracle数据库,由于电脑装的 ...
- Swagger-ui接口文档
参考地址 https://github.com/swagger-api/swagger-core/wiki/Annotations-1.5.X#quick-annotation-overview ...
- Flask 教程 第二十一章:用户通知
本文翻译自The Flask Mega-Tutorial Part XXI: User Notifications 这是Flask Mega-Tutorial系列的第二十一章,我将添加一个私有消息功能 ...
- wix中ServiceInstall与ServiceControl的关系
上面那篇之后其实还踩了个坑,安装Windows服务确实是打包进去了,但死活不能安装成功,从提示和日志看正好是Windows服务处理的地方出现了异常.以为是服务启动失败,但是服务在服务管理里手动启动是没 ...
- 妙用python之编码转换
转自i春秋 文章难易度:★★ 知识点:python.编码转换 前 言 在日常渗透,漏洞挖掘,甚至是CTF比赛中,会遇到各种编码,常常伴随着这些编码之间的各种转换.记得刚入门那个时候,自己处理编码转换问 ...
- Unity 鼠标旋转物体360展示
PC端 using UnityEngine; using System.Collections; public class DragRound : MonoBehaviour { public Tra ...
- Java8 Lambda使用指南
Java8 Lambda 的使用指南 原文地址:https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#s ...
- laravel搭建博客实战的教程实例
这篇文章主要给大家介绍了关于利用laravel搭建一个迷你博客的相关资料,文中将一步步的实现步骤通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面跟着来一起学习学习吧. 本文主 ...
- JS高级---利用原型共享数据
什么样子的数据是需要写在原型中? 需要共享的数据就可以写原型中 原型的作用之一: 数据共享 //属性需要共享, 方法也需要共享 //不需要共享的数据写在构造函数中,需要共享的数据写在原型中 //构造函 ...