自测之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 ...
随机推荐
- JFinal DB.tx()事务回滚及lambda表达式应用
JFinal DB.tx()事务回滚 在要往数据库操作多条数据时,就需要用到事务,JFinal中有封装好的事务应用 写法: Db.tx(new IAtom(){ @Override public bo ...
- 用原生JS写一个网页版的2048小游戏(兼容移动端)
这个游戏JS部分全都是用原生JS代码写的,加有少量的CSS3动画,并简单的兼容了一下移动端. 先看一下在线的demo:https://yuan-yiming.github.io/2048-online ...
- Jqgrid利用正则匹配表达式正确移除html标签
在使用JqGrid表格插件过程中,遇到一个问题:后台取出来的字段是带有Html标签的,于是将内容填充到表格之后,带有的html标签会把表格撑开或者每一行的内容显示不统一,导致非常难看,就像下图所示: ...
- canvas常用属性方法由浅下沉
首先引入<canvas></canvas>标签就不必说了. 其次就是得到canvas的2d环境了( var ctx = canvasDom.getContext('2d') ) ...
- QQ空间认证之数据篇
最近,我们发现可以利用开通企鹅媒体平台的方式开通QQ公众号从而绑定我们的QQ号,这样我们所绑定的QQ号就成了认证空间了. 虽说这样很快捷的就认证了我们的QQ空间,但是,起有利也有弊.任何事情都不是十全 ...
- MongoDB 4.0.6 Manual
General mongod options: -v [ --verbose ] [=arg(=v)] be more verbose (include multiple times for more ...
- 新系统设置 github 私钥
1.首先我得重新在git设置一下身份的名字和邮箱(因为当初都忘了设置啥了,因为遇到坑了)进入到需要提交的文件夹底下(因为直接打开git Bash,在没有路径的情况下,根本没!法!改!刚使用git时遇到 ...
- python学习笔记:第21天 常用内置模块之collections和time
目录 一.collections模块 二.时间模块 也可以在我的个人博客上阅读 一.collections模块 1. Counter Counter是⼀个计数器,主要⽤统计字符的数量,之前如果我们要统 ...
- malloc、calloc、realloc函数说明
malloc 函数 #include <stdlib.h> void* malloc(int n); n为要分配的字节数,如果成功,返回获得空间的首地址,如果分配失败,则返回NULL,ma ...
- HyperLedger Fabric 1.4 基础环境搭建(7)
学习了前面几章理论知识后,本章开始介绍实践操作,先介绍Fabric基础环境搭建,采用的操作系统为Centos 7 64位,依次介绍Docker安装.Docker-Compose安装.GO语言环境安装. ...