c语言网络通信_c语言tcp网络编程

c语言网络通信_c语言tcp网络编程目录TCP/IP协议介绍TCP/IP协议与WinSock网络编程接口的关系WinSock编程简单流程VC中socket编程·服务器实现·客户端实现测试结果TCP/IP协议介绍TCP/I…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

目录

        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所示的系统调用使用顺序:

c语言网络通信_c语言tcp网络编程

        注意:上面的代码没有任何检查函数返回值,如果你作网络编程就一定要检查任何一个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语言网络通信_c语言tcp网络编程

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/179419.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • mac os+selenium2+chrome驱动+python3

    mac os+selenium2+chrome驱动+python3macos10.11.5+python3安装selenium过程详解(附截图),难点在chrome驱动安装,以及第一个selenium自动化脚本

  • r语言求置信区间的函数_r语言区间估计

    r语言求置信区间的函数_r语言区间估计转载链接:https://www.codesd.com/item/confidence-interval-of-coefficients-using-the-generalized-estimation-equation-ege.html.链接:https://stackoverflow.com/questions/21221280/confidence-interval-of-coefficients-using-generalized-estimating-equation-gee.需要明确,

  • 全新安装Mac OSX 开发者环境 同时使用homebrew搭建 (LNMP开发环境)

    全新安装Mac OSX 开发者环境 同时使用homebrew搭建 (LNMP开发环境)

  • Nginx搭建视频点播和视频直播服务器[通俗易懂]

    Nginx搭建视频点播和视频直播服务器[通俗易懂]Nginx搭建视频点播和视频直播服务器一·、环境:Centos7,(推荐,Ubuntu不是很好用,经常会有一些莫名其妙的报错)Nginx1.10.1二、系统环境搭建首先,我是不建议自己一个个去安装这些软件的,耗时耗力,而且,容易出错,所以,最好使用yuminstall***命令安装,出错的概率小。资源链接:链接:https://pan.baidu.com/s/1WmJYpQ_b…

  • 安卓反编译_apk可以反编译吗

    安卓反编译_apk可以反编译吗本帖最后由好奇害死猫咪啊于2017-5-621:48编辑本教程为长期更新贴,有问题请及时反馈。如有更新请恕不另行通知。【前言】闲来无事水一贴。。。今天写个教程吧,反编译SystemUI实现状态栏时钟居中。其实说实话本来对华为靠右边的时间不怎么介意的,可一位朋友说什么也想换成类似iPhone的居中式,甚至不惜去刷XP框架,装重力工具箱。。当然了,结果大家可能已经想到了,首先是重力工…

  • 无线点餐系统服务器源代码,android 无线点餐系统,源码

    无线点餐系统服务器源代码,android 无线点餐系统,源码【实例简介】android无线点餐系统,源码,能直接运行。【实例截图】【核心代码】0jzexo└──无线点餐系统├──server│├──bin││├──clientServer.class││└──com││└──vista││└──Server││├──Selec…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号