基于TCP和UDP的客户端和服务器端

  • 一、 实验要求
  • 二、实验目的
  • 三、 实验环境
  • 四、 实验内容
  • 五、 实验原代码
  • 六、 实验结论
  • 七、 实验错误及改正
  • 八、 总结

一、 实验要求

(1)分别编写基于TCP和UDP的Windows和Linux程序客户端和服务器端;
(2)实现TCP客户端和服务器端之间的基本的数据收发;
(3)实现UDP客户端和服务器端之间的基本的数据收发;

二、实验目的

(1)掌握基于C语言的Socket编程相关函数和数据类型;
(2)掌握WIN32和Linux操作系统下的程序的基本编程方法,以及TCP、UDP编程的基本方法;
(3)熟练掌握UDP、TCP 客户端/服务器端模式的通信原理,及编程命令;

三、 实验环境

Windows 2007,DEV C++。

四、 实验内容

一个简单的客户机/服务器程序的实现。基本原理:
服务器端:
(1)调用socket函数创建套接字;
(2)调用bind函数绑定socket和端口号;
(3)调用listen函数监听连接请求;
(4)调用accept函数接收来自客户端的连接请求;
(5)调用send()、recv()函数和read()、write()函数进行数据的传输;
(6)调用close()函数关闭套接字;
客户端:
(1)调用socket()函数创建套接字;
(2)调用connect()函数连接指定服务器的端口;
(3)调用send()、recv()函数和read()、write()函数进行数据的传输;
(4)调用close()函数关闭套接字;

五、 实验原代码

(1)服务端代码

1.   #include<stdio.h>
2.  #include<stdlib.h>
3.  #include<string.h>
4.  #include<winsock2.h>
5.
6.  #define BUF_SIZE 1024
7.  void ErrorHandling(char *message);
8.
9.  int main(int argc,char *argv[])
10. {
11.     WSADATA wsaData;//定义数据类型
12.     SOCKET hServSock,hClntSock;
13.     char message[BUF_SIZE];//消息数组
14.     int strLen,i;
15.     SOCKADDR_IN servAdr,clntAdr;//指明地址信息
16.     int clntAdrSize;
17. //初始化个变量,以及定义结构体
18.     if(argc!=2)//输入两个值
19.     {
20.         printf("Usage : %s <port>\n", argv[0]);
21.         exit(1);
22.     }
23.
24.     if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
25. /*windows环境下的winsock初始化,成功返回0,失败返回非0的错误代码,
26. 第一个参数表示程序员需要用到的winsock版本 ,第二个表示WSADATA结构体变量的地址*/
27.        ErrorHandling("WSAStartup() error!");//代码出错
28.
29.     hServSock=socket(PF_INET,SOCK_STREAM,0);//调用socket函数创建套接字
30.     if(hServSock==INVALID_SOCKET)//socket创建的套接字为无效套接字
31.         ErrorHandling("socket() error");
32.
33.     memset(&servAdr,0,sizeof(servAdr));//初始化地址结构体信息
34.     servAdr.sin_family=AF_INET;//sin_family指代协议族,在socket编程中只能是AF_INET
35.     servAdr.sin_addr.s_addr=htonl(INADDR_ANY);//sin_addr存储IP地址,使用in_addr这个数据结构
36.     //htonl函数将一个32位数从主机字节顺序转换成网络字节顺序。
37.     servAdr.sin_port=htons(atoi(argv[1]));//sin_port存储端口号(使用网络字节顺序)
38.     /*htons是将整型变量从主机字节顺序转变成网络字节顺序,
39.     就是整数在地址空间存储方式变为高位字节存放在内存的低地址处。
40.     atoi (表示 ascii to integer)是把字符串转换成整型数的一个函数*/
41.     if(bind(hServSock,(SOCKADDR*)&servAdr,sizeof(servAdr))==SOCKET_ERROR)
42.     /*绑定,即给创建好的套接字分配IP地址和端口号 */
43.         ErrorHandling("bind() error");
44.
45.     if(listen(hServSock,5)==SOCKET_ERROR)//监听,将套接字转换成可接收的连接状态,调用其客户端的连接
46.     /*listen函数进入等待连接请求状态,成功返回0,失败返回-1,
47.     hServSock表示进入等待的套接字文件描述符(监听套接字),
48.     5:表示连接请求队列长度,表示最多有5个连接请求进入队列*/
49.         ErrorHandling("listen() error");
50.
51.     clntAdrSize=sizeof(clntAdr);//调用5次
52.
53.     for(i=0;i<5;i++)
54.     {
55.         hClntSock=accept(hServSock,(SOCKADDR*)&clntAdr,&clntAdrSize);
56.         /*调用其受理客户端连接请求,成功返回套接字句柄,失败返回INVALID_SOCKET
57.         hServSock:套接字文件描述符,
58.         (SOCKADDR*)&clntAdr:保存发起连接请求的客户端地址信息的变量地址,服务端的地址信息
59.         &clntAdrSize:结构体的长度,函数调用完后,该变量呗填入客户端地址长度*/
60.         if(hClntSock==-1)
61.            ErrorHandling("accept() error");
62.         else
63.             printf("Connected client %d \n",i+1);
64.
65.     while((strLen=recv(hClntSock,message,BUF_SIZE,0))!=0)
66.     /*接收数据,成功时返回套接字的字节数(收到EOF时为0),失败时返回SOCKET_ERROR。
67.     第一个参数表示数据接收对象连接的套接字句柄,2:表示保存数据的缓冲区地址;
68.     3:表示能够接收的最大字节序;第4个参数表示接收数据时用到的多种选项信息*/
69.         send(hClntSock,message,strLen,0);
70.     /*发送数据,成功时返回传输的字节数,失败时返回SOCKET_ERROR*/
71.     closesocket(hClntSock);
72.     }
73.     closesocket(hServSock);//关闭套接字
74.     WSACleanup();//int WSACleanup(void)成功时返回0,失败返回SOCK_ERROR。注销该库
75.     return 0;
76. }
77.
78. void ErrorHandling(char *message)
79. {
80.     fputs(message,stderr);
81.     fputc('\n',stderr);
82.     exit(1);
83. }
84.

(2)客户端

1.   #include<stdio.h>
2.  #include<stdlib.h>
3.  #include<string.h>
4.  #include<winsock2.h>
5.
6.  #define BUF_SIZE 1024
7.  void ErrorHandling(char *message);
8.
9.  int main(int argc,char *argv[])
10. {
11.     WSADATA wsaData;
12.     SOCKET hSocket;
13.     char message[BUF_SIZE];
14.     int strLen;
15.     SOCKADDR_IN servAdr;//初始化地址信息
16.
17.     if(argc!=3){
18.         printf("Usage : %s <IP> <port>\n", argv[0]);
19.         exit(1);
20.     }
21.
22.     if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
23.        ErrorHandling("WSAStartup() error!");
24.
25.     hSocket=socket(PF_INET,SOCK_STREAM,0);    //创建套接字 ,
26.
27.     if(hSocket==INVALID_SOCKET)
28.        ErrorHandling("scoket() error");
29.
30.     memset(&servAdr,0,sizeof(servAdr));//初始化地址结构体信息
31.     servAdr.sin_family=AF_INET;
32.     servAdr.sin_addr.s_addr=inet_addr(argv[1]);
33.     servAdr.sin_port=htons(atoi(argv[2]));
34.
35.     if(connect(hSocket,(SOCKADDR*)&servAdr,sizeof(servAdr))==SOCKET_ERROR)
36.         ErrorHandling("connect() error!");
37.     else
38.        puts("Connected.......");
39.
40.     while(1)
41.     {
42.         fputs("Input message(Q to qiut): ",stdout);//从终端获取一个字符串
43.         fgets(message,BUF_SIZE,stdin);
44.         if(!strcmp(message,"q\n")|| !strcmp(message,"Q\n"))
45.            break;
46.
47.         send(hSocket,message,strlen(message),0);
48.         strLen=recv(hSocket,message,BUF_SIZE-1,0);
49.         message[strLen]=0;
50.         printf("Message from server: %s",message);
51.     }
52.     closesocket(hSocket);
53.     WSACleanup();
54.     return 0;
55.  }
56.
57. void ErrorHandling(char *message)
58. {
59.     fputs(message,stderr);
60.     fputc('\n',stderr);
61.     exit(1);
62. }

六、 实验结论

服务端代码编译运行结果截图:

第一段代码表示第一个客户连接到回声服务端,接收到服务并终止连接。
客户端代码编译运行结果截图:

回声服务器端/客户端以字符串为单位传输数据,服务端接收到信息后反馈给客户端。

七、 实验错误及改正

(一)错误一:实验环境
(1)错误一描述:在DEV C++环境下编译代码发现代码编译出错,通过检查发现代码并没有错误,compiler报错提示为:link环境出错,找不到套接字相关文件(以client_win.c文件为例)。

(2)错误分析:通过查阅相关资料以及与同学商量,发现是需要配置link环境,网络编程需要导入头文件winsock2.h,以及链接ws2_32.lib库,预实验我是按照上课老师演示的方法在visual C++6.0版本下更改链接库,编译成功并且通过,实验室是按照在DEV C++环境下编程,更改步骤为:tools——>Compiler Options——>General——>add(-lwsocke32)

(3)更改链接库后问题解决,编译通过。在Windows环境由于不同的软件,在开发网络编程时更改环境变量的位置与方法也不相同,Visual studio 2008版本添加链接库的步骤为:选择“配置属性”——>“输入”——>“附加依赖项”也可以通过快捷键AIT+F7打开属性页。通过配置链接库,我也明白到,套接字编程与C语言类似也有相应的链接库,不同的函数,要学会调用。

(二)错误二:编译通过,运行与题目不符合。
(1)错误二来源:代码出错,通过编译,运行结果显示套接字连接错误。

(2)错误分析:找到connect error的原因以及相关代码,通过分析,发现是如下语句会提示错误:

  1. if(connect(hSocket,(SOCKADDR*)&servAdr,sizeof(servAdr))==SOCKET_ERROR)
  2.      ErrorHandling("connect() error!");
    

通过分析,connect()函数中的hSocket套接字没有赋值。
(3)错误改正与总结:
在main()函数下为hsocket赋值,语句如下:

  1. hSocket=socket(PF_INET,SOCK_STREAM,0); //创建套接字
    添加该语句后编译通过。

八、 总结

根据数据传输方式的不同,基于网络协议的套接字一般分成TCP套接字和UDP套接字。
TCP套接字是面向连接的,又称为基于流Stream的套接字,TCP,TCP/IP协议栈分成4层架构。不同于OSI 7层架构:物理层–>数据链路层–>网络层–>传输层–>会话层–>表示层–>应用层。实验实习的是TCP实现基于TCP的服务器端和客户端:

  1. 链路层:是物理链接领域标准化的结果,也是最基本的领域,
    专门定义LAN,WAN,MAN等网络标准。
  2. IP层:复杂网络中,负责路径的选择。IP本身是面向消息的,不可靠的协议。
  3. TCP/UDP层:已IP层提供的路劲信息为基础完成实际的数据传输,
    因此也称为传输层。TCP比UDP复杂,TCP可以保证可靠的数据传输。
  4. 应用层:根据程序特点决定服务器端和客户端之间数据传输规则。

实验一 基于TCP和UDP的客户端和服务器端相关推荐

  1. 基于TCP和UDP的socket

    为什么学习socket 你自己现在完全可以写一些小程序了,但是前面的学习和练习,我们写的代码都是在自己的电脑上运行的,虽然我们学过了模块引入,文件引入import等等,我可以在程序中获取到另一个文件的 ...

  2. 基于tcp和udp的socket实现

    2019独角兽企业重金招聘Python工程师标准>>> 本文介绍如何用Java实现Socket编程.首先介绍Java针对Socket编程提供的类,以及它们之间的关系.然后分别针对TC ...

  3. Node.js实现基于TCP与UDP的数据通信

    2019独角兽企业重金招聘Python工程师标准>>> 7.1.使用net模块实现基于TCP的数据通信 7.1.1.创建TCP服务器 在node.js中可以很方便的创建一个TCP服务 ...

  4. TCP/IP网络编程之基于TCP的服务端/客户端(一)

    TCP/IP网络编程之基于TCP的服务端/客户端(一) 理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP套接字和UDP套接字.因为TCP套接字是面向连接的,因此又称为基于 ...

  5. 群聊系统项目(基于TCP、UDP实现)

    最近学习了网络编程后, 写了一个基于TCP.UDP协议的群聊系统. 技术栈 1.TCP.UDP通信       2.生产.消费模型, 支持并发       3.自定义协议封装数据 & json ...

  6. 【Socket网络编程】4.tcp和udp的客户端和服务端收发流程

    tcp和udp的客户端和服务端收发流程 1.udp服务器流程: 1.创建serverSocket 2.设置服务器地址 serverAddr 3.将serverSocket和serverAddr绑定 b ...

  7. TCP/IP网络编程之基于TCP的服务端/客户端(二)

    回声客户端问题 上一章TCP/IP网络编程之基于TCP的服务端/客户端(一)中,我们解释了回声客户端所存在的问题,那么单单是客户端的问题,服务端没有任何问题?是的,服务端没有问题,现在先让我们回顾下服 ...

  8. c udp文件发送到服务器端,基于UDP的客户端和服务器端的代码设计

    实验平台 linux 实验内容 编写UDP服务器和客户端程序,客户端发送消息,服务器接收消息,并打印客户端的IP地址和端口号. 实验原理 UDP是无需连接的通信,其主要实现过程如下: 同样,我们可以按 ...

  9. Node.js权威指南 (7) - 实现基于TCP与UDP的数据通信

    7.1 使用net模块实现基于TCP的数据通信 / 136 7.1.1 创建TCP服务器 / 136 7.1.2 socket端口对象 / 142 7.1.3 创建TCP客户端 / 151 7.1.4 ...

最新文章

  1. 基于Linux GlassFish v3 配置取代tomcat
  2. Chrome浏览器插件OneTab标签聚合插件
  3. 软件需求分层处理的多种常见方式
  4. 43 | 套路篇:网络性能优化的几个思路(上)
  5. JavaScript event loop事件循环 macrotask与microtask
  6. MicroStation V8i简体中文版中文字体乱码解决办法
  7. 标签 href 怎么拼接_【微信】用户-标签的兴趣建模
  8. 链接脚本文件(*.lds)
  9. 数据中心多余的热量去哪儿了?
  10. 用MVC做可拖拽的留言板,利用 Jquery模板 -- JsRender
  11. java 从后往前截取_java 字符串截取的实例详解
  12. 【魔兽世界插件】魔兽世界插件实战笔记从入门到放弃的心理历程 第五节 窗体文字材质设置
  13. 2017/7/11 新开博客
  14. 源代码安全加密解决方案
  15. MySQL安装2出现Typical_Mysql安装 - osc_c7lpn2ge的个人空间 - OSCHINA - 中文开源技术交流社区...
  16. 群晖自动删除重复文件_在群晖中批量删除重复文件(零基础手把手图文)
  17. windows7 为系统盘瘦身
  18. 2021-10-22 KiKi定义电子日历类
  19. 敏捷组织转型之路-杨锋镝
  20. 把pdf转换成ppt的软件

热门文章

  1. JS——nth-child和nth-of-type的区别以及nth-of-type下的坑
  2. 用 zCloud 解锁智能运维,“以小为美”的苏州银行成就数字化转型“大作为”...
  3. C++设计模式——访问者模式(高屋建瓴)
  4. linux运行欧陆风云,释放强大性能:Linux内核迎来QMEU 6.0的M68k虚拟机补丁
  5. 并联串联混合的电压和电流_困惑了很久的串联/并联谐振电路详解
  6. 【嵌入式模块】FT232RL——一个带有ISP功能的USB转TTL模块
  7. [篇五章三]-关于 Windows 10 安装好后系统自带的微软输入法没有输入框的 BUG 解决办法
  8. Hawk-and-Chicken详解
  9. dell 720 raid 配置
  10. 09.JSP自定义标签01