自测之Lesson15:TCP&UDP网络编程
题目:编写一个TCP通信的程序。
实现代码:
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h> #define PORT 0xaaaa // 服务端
void startServe()
{
int iRet; // socket()
int fd; // 文件描述符
fd = socket(PF_INET, SOCK_STREAM, 0); // 创建文件描述符,并确定是用TCP还是UDP等
if (fd < 0) {
perror("fail socket");
return;
} // bind()
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 即使目标地址不是我,只要发到该计算机上,我就能接收 iRet = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); // 将文件描述符与本机地址绑定
if (iRet < 0) {
perror("fail bind");
close(fd); // 释放资源
return;
} // listen()
iRet = listen(fd, 5); // 最多监听5个连接请求
if (iRet < 0) {
perror("fail listen");
close(fd);
return;
}
printf("Server start OK, wait connect...\n"); // accept()
char szBuf[1024];
char szMsg[] = "Welcome...";
struct sockaddr_in clientAddr; // 客户端地址
socklen_t addrlen = sizeof(clientAddr);
while(1) {
int newFd; // 此newFd用于与客户端通信
newFd = accept(fd, (struct sockaddr*)&clientAddr, &addrlen);
if (newFd < 0) {
perror("fail accept");
break;
} char *pClientAddr = inet_ntoa(clientAddr.sin_addr); // 整数IP转字符串IP
int clientPort = ntohs(clientAddr.sin_port); // 网络字节序转主机字节序
printf("Connect from %s:%d\n", pClientAddr, clientPort);
memset(szBuf, 0, 1024);
iRet = read(newFd, szBuf, 1024);
if (iRet < 0) {
perror("fail read");
break;
}
printf("Recv:%s\n", szBuf);
write(newFd, szMsg, strlen(szMsg));
close(newFd); // 关闭当前accept创建的文件描述符
}
close(fd);
return;
} // 客户端
void startClient()
{
int iRet; // socket()
int fd;
fd = socket(PF_INET, SOCK_STREAM, 0);
if(fd < 0) {
perror("fail socket");
return;
} // connect()
struct sockaddr_in srvAddr;
srvAddr.sin_family = AF_INET;
srvAddr.sin_addr.s_addr = inet_addr("192.168.85.128"); // 服务端的ip地址
srvAddr.sin_port = htons(PORT); // 服务端的端口号
iRet = connect(fd, (struct sockaddr*)&srvAddr, sizeof(srvAddr));
if (iRet != 0) {
perror("fail connect");
return;
}
printf("Connect success\n");
fprintf(stderr, "Send:"); // read() & write()
char szBuf[1024];
memset(szBuf, 0, 1024);
read(STDIN_FILENO, szBuf, 1024); // 从标准输入 输入消息
write(fd, szBuf, strlen(szBuf));
char szRcv[1024]; memset(szRcv, 0, 1024);
read(fd, szRcv, 1024);
printf("[CLIENT]Rcv:%s\n", szRcv); close(fd);
return;
} int main(int argc, char **argv)
{
if (argc != 2 ||
(strcmp(argv[1], "s") && strcmp(argv[1], "c"))) {
printf("Usage: %s [ s | c ]\n", argv[0]);
printf("\ts: start server\n");
printf("\tc: start client\n");
return 0;
}
if (argv[1][0] == 's') {
startServe();
}
else if (argv[1][0] == 'c') {
startClient();
}
return 0;
} /* ReadMe */
/*
* 先启动服务端 --> ./a.out s
* 再启动客户端 --> ./a.out c
*/
题目:编写一个UDP通信的程序。
实现代码:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h> #define SRV_PORT 0xaaaa // 服务端 端口号
#define CLI_PORT 0xbbbb // 客户端 端口号
#define IP_ADDRESS "10.162.73.120" void startServer()
{
int iRet; // socket()
int fd;
fd = socket(PF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("fail socket");
return;
} // bind()
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SRV_PORT);
iRet = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
if (iRet != 0) {
perror("fail bind");
return;
} // recvfrom() & sendto()
struct sockaddr_in cliAddr;
socklen_t addrLen = sizeof(cliAddr);
char szRcv[1024];
char szSnd[1024];
while(1) {
// recvfrom()
memset(szRcv, 0, 1024);
iRet = recvfrom(fd, szRcv, 1024, 0, (struct sockaddr*)&cliAddr, &addrLen);
if (iRet < 0) {
perror("fail recvfrom");
close(fd);
break;
}
char *pcliAddr = inet_ntoa(cliAddr.sin_addr);
int cliPort = ntohs(cliAddr.sin_port);
printf("Recv from client[%s:%d]\n", pcliAddr, cliPort);
printf("Recv:%s\n", szRcv); // sendto()
fprintf(stderr, "Send:");
memset(szSnd, 0, 1024);
read(STDIN_FILENO, szSnd, 1024);
iRet = sendto(fd, szSnd, strlen(szSnd), 0, (struct sockaddr*)&cliAddr, addrLen); }
close(fd);
} void startClient()
{
int iRet; // socket()
int fd;
fd = socket(PF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("fail socket");
return;
} // bind()
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(CLI_PORT);
iRet = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
if (iRet != 0) {
perror("fail bind");
return;
} // recvfrom() & sendto()
struct sockaddr_in srvAddr;
socklen_t addrLen = sizeof(srvAddr);
// 对端的地址信息,用于sendto()函数
srvAddr.sin_family = AF_INET;
srvAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
srvAddr.sin_port = htons(SRV_PORT);
char szRcv[1024];
char szSnd[1024];
while(1) {
// sendto()
fprintf(stderr, "Send:");
memset(szSnd, 0, 1024);
read(STDIN_FILENO, szSnd, 1024);
sendto(fd, szSnd, strlen(szSnd), 0, (struct sockaddr*)&srvAddr, addrLen); // read()
memset(szRcv, 0, 1024);
read(fd, szRcv, 1024); // 上面的sendto()已经获得对端地址,此处可简写
printf("Recv:%s\n", szRcv);
}
close(fd);
} int main(int argc, char **argv)
{
if (argc != 2 ||
(strcmp(argv[1], "c") && strcmp(argv[1], "s")))
{
printf("Usage:%s [ s | c ]\n", argv[0]);
printf("\ts: start to server\n");
printf("\tc: start to client\n");
return 0;
}
if (argv[1][0] == 's') {
startServer();
}
else if (argv[1][0] == 'c') {
startClient();
}
return 0;
}
题目:编写一个抓包程序,要求抓取封装TCP报文段的包,并打印出包的头部信息。
实现代码:
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h> #define PORT 0Xaaaa // 此端口仅用于bind(),而该程序可抓发送到任意端口的包 typedef struct _ipHeader {
// unsigned char ucVer:4;
// unsigned char ucHeadLen:4;
unsigned char ucVerHeadLen; // 不应该在此处用位域,可在后面提取位数
unsigned char ucTos;
unsigned short usLen;
unsigned short usIdent;
// unsigned short usFlag:3;
// unsigned short usOffset:13;
unsigned short usFlagOffset;
unsigned char ucTTL;
unsigned char ucProtocol;
unsigned short usChkSum;
// unsigned int uiSrcIp;
// unsigned int uiDestIp;
struct in_addr SrcIp;
struct in_addr DestIp;
char data[0];
} IP_HEADER; typedef struct _tcpHeader {
unsigned short SrcPort;
unsigned short DestPort;
unsigned int Seq;
unsigned int Ack;
// unsigned short HeadLen:4;
// unsigned short Save:6;
// unsigned short URG:1;
// unsigned short ACK:1;
// unsigned short PSH:1;
// unsigned short RST:1;
// unsigned short SYN:1;
// unsigned short FIN:1;
unsigned short HeadLenFlag; // 包括首部长度、保留、URG标志等字段
unsigned short Window;
unsigned short ChkSum;
unsigned short UrgPoint;
char data[0];
} TCP_HEADER; void printIpHeader(char szBuf[])
{
IP_HEADER *pHeader = (IP_HEADER*)szBuf;
printf("\n================IP HEADER================\n");
printf("\tVersion:%d\n", (pHeader->ucVerHeadLen) >> 4);
printf("\tHeadLen:%d\n", (pHeader->ucVerHeadLen) & 0x0f);
printf("\tSOUR IP:%s\n", inet_ntoa(pHeader->SrcIp));
printf("\tDEST IP:%s\n", inet_ntoa(pHeader->DestIp));
printf("=========================================\n");
} void printTcpHeader(char szBuf[])
{
TCP_HEADER *pHeader = (TCP_HEADER*)szBuf;
printf("\n===============TCP HEADER================\n");
printf("\tSOUR PORT:%d\n", ntohs(pHeader->SrcPort));
printf("\tDEST PORT:%d\n", ntohs(pHeader->DestPort));
printf("=========================================\n");
} void startCapturePacket()
{
int iRet; int fd;
fd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP/* = NUM'6' */); // 抓取封装TCP报文段的IP数据报
if (fd < 0) {
perror("fail socket");
return;
} struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY); iRet = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
if (iRet < 0) {
perror("fail bind");
close(fd);
return;
} char szBuf[1024];
while(1) {
memset(szBuf, 0, 1024);
read(fd, szBuf, 1024); // 将抓到的包整个存到szBuf中,此处szBuf的大小不是很合适
printIpHeader(szBuf); // 打印IP头部部分信息
printTcpHeader(szBuf); // 打印TCP报文端头部部分信息
}
close(fd);
return;
} int main()
{
startCapturePacket();
return 0;
}
自测之Lesson15:TCP&UDP网络编程的更多相关文章
- TCP/UDP网络编程的基础知识与基本示例(windows和Linux)
一.TCP编程的一般步骤 服务器端: 1.创建一个socket,用函数socket() 2.绑定IP地址.端口等信息到socket上,用函数bind() 3.开启监听,用函数listen() 4.接收 ...
- JAVA UDP网络编程学习笔记
一.UDP网络编程概述 采用TCP协议通信时,客户端的Socket必须先与服务器建立连接,连接建立成功后,服务器端也会持有客户端连接的Socket,客户端的Socket与服务器端的Socket是对应的 ...
- 三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层
这篇文章主要是来做(da)推(guang)介(gao)的!由于这两年接触到了比较多的这方面的知识,不想忘了,我决定把他们记录下来,所以决定在GitBook用半年时间上面写下来,这是目前写的一节,后面会 ...
- 《TCP/IP网络编程》
<TCP/IP网络编程> 基本信息 作者: (韩)尹圣雨 译者: 金国哲 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:9787115358851 上架时间:2014-6- ...
- TCP/IP网络编程系列之四(初级)
TCP/IP网络编程系列之四-基于TCP的服务端/客户端 理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP和UDP套接字.因为TCP套接字是面向连接的,因此又称为基于流的 ...
- TCP/IP网络编程系列之三(初级)
TCP/IP网络编程系列之三-地址族与数据序列 分配给套接字的IP地址和端口 IP是Internet Protocol (网络协议)的简写,是为首发网络数据而分配给计算机的值.端口号并非赋予计算机值, ...
- TCP/IP网络编程之多播与广播
多播 多播方式的数据传输是基于UDP完成的,因此,与UDP服务端/客户端的实现非常接近.区别在于,UDP数据传输以单一目标进行,而多播数据同时传递到加入(注册)特定组的大量主机.换言之,采用多播方式时 ...
- TCP/IP网络编程之套接字的多种可选项
套接字可选项进而I/O缓冲大小 我们进行套接字编程时往往只关注数据通信,而忽略了套接字具有的不同特性.但是,理解这些特性并根据实际需要进行更改也十分重要.之前我们写的程序在创建好套接字后都是未经特别操 ...
- TCP/IP网络编程之基于TCP的服务端/客户端(一)
理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP套接字和UDP套接字.因为TCP套接字是面向连接的,因此又称为基于流(stream)的套接字.TCP是Transmissi ...
随机推荐
- Qt5应用程序封包
系统环境:windows10+vs2017+qt5.12 目的:生成.exe可执行文件. 步骤: 1.选择release模式,生成解决方案. 2.打开命令行,cd到生成的可执行文件.exe目录下 3. ...
- 2018 Wannafly summer camp Day8--连通块计数
连通块计数 描述 题目描述: 小 A 有一棵长的很奇怪的树,他由 n 条链和 1 个点作为根构成,第 i条链有 ai 个点,每一条链的一端都与根结点相连. 现在小 A 想知道,这棵长得奇怪的树有多少 ...
- Jquery中菜单的展开和折叠
jquery内容 <script> $(function () { $("dl dt").click(function () { $(this).siblings(). ...
- AJAX 动态加载后台数据 绑定select
<select id="select"> <!--下拉框数据动态加载--> </select> js:(使用jquery) $(document ...
- 用Python代码实现微信跳一跳作弊器
最近随着微信版本的更新,在进入界面有个跳一跳的小游戏,在网上看到技术篇教你用Python来玩微信跳一跳 ( 转载自 " 工科给事中的技术博客 " ) 本文旨在总结,技术全靠大神完成 ...
- 安装jenkins环境之jdk8
Launchpad PPA Repositories是很有用的非ubuntu官方的第三方个人资源库,可以很方便地安装第三方软件. 但是在运行add-apt-repository命令时,有时会提示命令不 ...
- php源码建博客4--实现MVC结构微型框架
主要: 常量优化路径 自动加载类 优化入口文件 安全访问项目目录 --------------文件结构:-------------------------------------- blog├─App ...
- python remove跟pop的区别
remove根据值来删除 li=[1,2,3,4] li.pop[0] li.remove['] 或者是a=li[-1]li.remove(a) pop是根据索引来删除
- json传值给前端页面,出现堆栈溢出问题
用的com.alibaba.fastjson.JSONObject这个包 原因:JSONObject将对象转json字符串时候没有关闭循环引用导致的堆栈溢出. 解决办法是 使用这个 JSONObjec ...
- 传说是小米家的一道面试题难倒了某Java程序员。扑克牌排序问题。
网上说的是有位网友在面试小米Java岗三次后,终于挺进了第三轮面试,结果还是败在了两道算法题上面. 1.写个读方法和写方法,实现读写锁 2.一副从1到n的牌,每次从牌堆顶取一张放桌子上,再取一张放牌堆 ...