C语言实现网络聊天程序的设计与实现(基于TCP协议)
目录
TCP/IP协议介绍
TCP/IP协议与WinSock网络编程接口的关系
WinSock编程简单流程
VC中socket编程
·服务器实现
·客户端实现
测试结果
TCP/IP协议介绍
TCP/IP协议包含的范围非常的广,它是一种四层协议,包含了各种硬件、软件需求的定义。TCP/IP协议确切的说法应该是TCP/UDP/IP协议。UDP协议(User Datagram Protocol 用户数据报协议),是一种保护消息边界的,不保障可靠数据的传输。TCP协议(Transmission Control Protocol 传输控制协议),是一种流传输的协议。他提供可靠的、有序的、双向的、面向连接的传输。
保护消息边界,就是指传输协议把数据当作一条独立的消息在网上传输,接收端只能接收独立的消息。也就是说存在保护消息边界,接收端一次只能接收发送端发出的一个数据包。
而面向流则是指无保护消息边界的,如果发送端连续发送数据,接收端有可能在一次接收动作中,会接收两个或者更多的数据包。
举例来说,假如,我们连续发送三个数据包,大小分别是2k、4k、8k,这三个数据包都已经到达了接收端的网络堆栈中,如果使用UDP协议,不管我们使用多大的接收缓冲区去接收数据,我们必须有三次接收动作,才能够把所有的数据包接收完。而使用TCP协议,我们只要把接收的缓冲区大小设置在14k以上,我们就能够一次把所有的数据包接收下来,只需要有一次接收动作。
这就是因为UDP协议的保护消息边界使得每一个消息都是独立的。而流传输,却把数据当作一串数据流,它不认为数据是一个一个的消息。所以有很多人在使用TCP协议通讯的时候,并不清楚TCP是基于流的传输,当连续发送数据的时候,他们时常会认为TCP会丢包。其实不然,因为当它们使用的缓冲区足够大时,它们有可能会一次接收到两个甚至更多的数据包,而很多人往往会忽视这一点,只解析检查了第一个数据包,而已经接收的其它据包却被忽略了。
TCP/IP协议与WinSock网络编程接口的关系
WinSock 并不是一种网络协议,它只是一个网络编程接口,也就是说,它不是协议,但是它可以访问很多种网络协议,你可以把它当作一些协议的封装。现在的 WinSock已经基本上实现了与协议无关。你可以使用WinSock来调用多种协议的功能。那么,WinSock和TCP/IP协议到底是什么关系呢?实际上,WinSock就是TCP/IP协议的一种封装,你可以通过调用WinSock的接口函数来调用TCP/IP的各种功能.例如我想用TCP/IP 协议发送数据,你就可以使用WinSock的接口函数Send()来调用TCP/IP的发送数据功能,至于具体怎么发送数据,WinSock已经帮你封装好了这种功能。
WinSock编程简单流程
WinSock编程分为服务器端和客户端两部分,TCP服务器端的大体流程如下:
对于任何基于WinSock的编程首先必须要初始化WinSock DLL库。
int WSAStarup( WORD wVersionRequested,LPWSADATA lpWsAData )。
wVersionRequested是我们要求使用的WinSock的版本。
调用这个接口函数可以初始化WinSock 。
然后必须创建一个套接字(Socket)。
SOCKET Socket(int af,int type,int protocol);
套接字可以说是WinSock通讯的核心。WinSock通讯的所有数据传输,都是通过套接字来完成的,套接字包含了两个信息,一个是IP地址,一个是Port端口号,使用这两个信息,就可以确定网络中的任何一个通讯节点。
当调用了Socket()接口函数创建了一个套接字后,必须把套接字与你需要进行通讯的地址建立联系,可以通过绑定函数bind来实现这种联系。
int bind(SOCKET s,const struct sockaddr FAR* name,int namelen) ;struct sockaddr_in{short sin_family ;u_short sin_port;struct in_addr sin_addr ;char sin_sero[8] ;}
就包含了需要建立连接的本地的地址,包括地址族、IP和端口信息。sin_family字段必须把它设为AF_INET,这是告诉WinSock使用的是IP地址族。sin_port就是要用来通讯的端口号。sin_addr就是要用来通讯的IP地址信息。
在这里,必须还得提一下有关'大头(big-endian)'小头(little-endian)'。因为各种不同的计算机处理数据时的方法是不一样的,Intel X86处理器上是用'小头'形式来表示多字节的编号,就是把低字节放在前面,把高字节放在后面,而互联网标准却正好相反,所以,必须把主机字节转换成网络字节的顺序。WinSock API提供了几个函数。
把主机字节转化成网络字节的函数;
u_long htonl(u_long hostlong);u_short htons(u_short hostshort);
把网络字节转化成主机字节的函数;
u_long ntohl(u_long netlong);u_short ntohs(u_short netshort) ;
这样,设置IP地址和port端口时,就必须把主机字节转化成网络字节后,才能用Bind()函数来绑定套接字和地址。
当绑定完成之后,服务器端必须建立一个监听的队列来接收客户端的连接请求。
int listen(SOCKET s,int backlog);
这个函数可以把套接字转成监听模式。
如果客户端有了连接请求,我们还必须使用
int accept(SOCKET s,struct sockaddr FAR* addr,int FAR* addrlen);
来接受客户端的请求。
现在基本上已经完成了一个服务器的建立,而客户端的建立的流程则是初始化WinSock,然后创建Socket套接字,再使用
int connect(SOCKET s,const struct sockaddr FAR* name,int namelen) ;
来连接服务端。
下面是一个最简单的创建服务器端和客户端的例子:
服务器端的创建:
WSADATA wsd;SOCKET sListen;SOCKET sclient;UINT port = 800;int iAddrSize;struct sockaddr_in local , client;WSAStartup( 0x11 , &wsd );sListen = Socket ( AF_INET , SOCK_STREAM , IPPOTO_IP );local.sin_family = AF_INET;local.sin_addr = htonl( INADDR_ANY );local.sin_port = htons( port );bind( sListen , (struct sockaddr*)&local , sizeof( local ) );listen( sListen , 5 );sClient = accept( sListen , (struct sockaddr*)&client , &iAddrSize );
客户端的创建:
WSADATA wsd;SOCKET sClient;UINT port = 800;char szIp[] = "127.0.0.1";int iAddrSize;struct sockaddr_in server;WSAStartup( 0x11 , &wsd );sClient = Socket ( AF_INET , SOCK_STREAM , IPPOTO_IP );server.sin_family = AF_INET;server.sin_addr = inet_addr( szIp );server.sin_port = htons( port );connect( sClient , (struct sockaddr*)&server , sizeof( server ) );
当服务器端和客户端建立连接以后,无论是客户端,还是服务器端都可以使用
int send( SOCKET s,const char FAR* buf,int len,int flags);int recv( SOCKET s,char FAR* buf,int len,int flags);
函数来接收和发送数据,因为,TCP连接是双向的。
当要关闭通讯连接的时候,任何一方都可以调用
int shutdown(SOCKET s,int how);
来关闭套接字的指定功能,再调用
int closeSocket(SOCKET s) ;
来关闭套接字句柄,这样一个通讯过程就算完成了。
可以参考教材计算机网络(第6版)295页图6-32所示的系统调用使用顺序:
注意:上面的代码没有任何检查函数返回值,如果你作网络编程就一定要检查任何一个WinSock API函数的调用结果,因为很多时候函数调用并不一定成功。上面介绍的函数,返回值类型是int的话,如果函数调用失败的话,返回的都是SOCKET_ERROR。
VC中socket编程
·服务器实现
服务器端编程的步骤:
1:加载套接字库,创建套接字(WSAStartup()/socket());
2:绑定套接字到一个IP地址和一个端口上(bind());
3:将套接字设置为监听模式等待连接请求(listen());
4:请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept());
5:用返回的套接字和客户端进行通信(send()/recv());
6:返回,等待另一连接请求;
7:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。
服务器端代码如下:
#include <stdio.h>
#include <Winsock2.h>
void main()
{WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {return;}if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {WSACleanup( );return;}SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(6000);bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));listen(sockSrv,5);SOCKADDR_IN addrClient;int len=sizeof(SOCKADDR);while(1){SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);char sendBuf[50];sprintf(sendBuf,"Welcome %s to here!",inet_ntoa(addrClient.sin_addr));send(sockConn,sendBuf,strlen(sendBuf)+1,0);char recvBuf[50];recv(sockConn,recvBuf,50,0);printf("%s\n",recvBuf);closesocket(sockConn);}
}
·客户端实现
客户端编程的步骤:
1:加载套接字库,创建套接字(WSAStartup()/socket());
2:向服务器发出连接请求(connect());
3:和服务器端进行通信(send()/recv());
4:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。
客户端的代码如下:
#include <stdio.h>
#include <Winsock2.h>
void main()
{WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {return;}if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {WSACleanup( );return;}SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(6000);connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));send(sockClient,"hello",strlen("hello")+1,0);char recvBuf[50];recv(sockClient,recvBuf,50,0);printf("%s\n",recvBuf);closesocket(sockClient);WSACleanup();
}
测试结果
C语言实现网络聊天程序的设计与实现(基于TCP协议)相关推荐
- 计算机网络课程设计(一)网络聊天程序的设计与实现
实验题目 网络聊天程序的设计与实现 实验目的 1.了解Socket通信的原理,学会使用Socket进行简单的网络编程,在此基础上编写一个聊天程序. 2.了解Qt编程,熟悉C++语言. 总体设计 1.背 ...
- 计算机网络课程设计之网络聊天程序的设计与实现
前言 计算机网络课程设计开始,要求用C/C++,而且有些题目还要有图形界面,因此决定用Qt写图形界面,同时决定用一个程序完成所有的实验设计. 白嫖容易,创作不易,本文原创,转载请注明!!! 源码和可运 ...
- 计算机网络——网络聊天程序的设计与实现
计算机网络--网络聊天程序的设计与实现 一.实验目的 二.总体设计 1. 基本原理 2. 设计步骤 (1)服务器端编程的步骤 (2)客户端编程的步骤 三.详细设计 1. 程序流程图 2. 实验代码 ( ...
- 网络聊天程序的设计与实现
网络聊天程序的设计与实现 文章目录 网络聊天程序的设计与实现 一.实验题目 二.实验目的 三.背景知识 四.代码 一.实验题目 网络聊天程序的设计与实现 二.实验目的 使用socket编程,了解soc ...
- 网络聊天程序的设计与实现 python实现 计算机网络课程设计
设计内容: 一.了解 Socket 通信的原理,在此基础上编写一个聊天程序. 二.在实现聊天功能的基础上,使用Tkinter实现聊天的界面 代码 server from socket import * ...
- Java实现网络聊天程序的设计与实现(基于UDP协议)
目录 TCP/IP协议介绍 Java中socket编程 测试结果 TCP/IP协议介绍 TCP/IP协议包含的范围非常的广,它是一种四层 ...
- Linux网络编程:用C语言实现的聊天程序(同步通信)
通过TCP协议,用C语言实现的同步聊天程序,注释写的比较详细,个人觉得对字符串处理比较充分,能够正常编译运行,拿出来和大家分享一下! 1.客户端源代码: [cpp] view plaincopypri ...
- 基于Linux的网络编程——网络聊天程序
网络聊天程序是目前应用极为广泛的一种网络软件,对于方便人们的交流沟通非常有效,同时,作为一种典型的网络应用,编写网络聊天程序是学习基于Linux的网络编程的有效方法. 结合任务需求设计该程序,程序采用 ...
- 基于linux网络聊天室的设计,参考基于linux网络聊天室的设计.doc
参考基于linux网络聊天室的设计 长沙理工大学<高级操作系统>课程设计报告学 院 计算机与通信工程 专 业 计算机科学与技术 班 级 学 号 学生姓名 指导教师 课程成绩 完成日期 课程 ...
最新文章
- 如何在Windows上做Python开发?微软出了官方教程(附链接)
- oracle SQL not in null,单列,复合列
- php 聚类算法,科学网—matlab-聚类算法笔记 - 孙月芳的博文
- 前端学习(3009):vue+element今日头条管理--登录中的loding
- android-短信验证功能,Android实现获取短信验证码的功能以及自定义GUI短信验证详解...
- Valak 6个月上演“变身戏法”,紧盯 Exchange 服务器窃取企业数据
- 【转】PHP的执行原理/执行流程
- alexa工具条下载安装图解(支持51CTO的发展)
- fckeditor 源代码下载
- 计算机科学期刊重复率要求,计算机科学与应用期刊
- WeAdmin连接资源,相关错误
- 修改Element UI自带的小图标,替换成自己的(类似自定义Element UI图标)
- 使用stream将List转换为用逗号拼接的字符串
- java初级笔记(翁恺男神
- 揭秘 2023 年 Navicat 两大重磅功能 Redis + OceanBase 发布计划
- 项目揭秘:公众号小说赚钱与推广的暴利玩法(干货)
- [Solved] Pycharm 提示Unresolved reference
- 《OSPF和IS-IS详解》一1.7 独立且平等
- 【金融】新成立基金建仓时点、行业分布与市场行情关系探究
- Java与数据库中的datetime Timestamp以及String之间的转换
热门文章
- lstrip在python中是什么意思_“男怕属鸡,女怕属羊”,是什么意思?有什么讲究吗?...
- IO流(input /output)
- html-3 文字阴影
- debian linux root登录,DEBIAN 10切换ROOT用户登录
- 什么是“双机系统”?
- python程序设计-Python 异步编程入门
- excel 列标 数字恢复为字母的设置
- Android桌面快捷方式兼容问题
- jQuery实现一个农场小游戏
- Spring Boot教程(十三):Spring Boot文件上传