1. TCP server client模拟聊天对话框
server.c
/* server.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFFER_SIZE (1024)
#define IP_SIZE (100)
#define SERVER_SUCCESS (0)
#define SERVER_FAILURE (-1)
#define MAX_PENDDING_QUEUE (10)
typedef enum {
false = 0,
true = 1,
} bool;
static void server_usage(void)
{
printf("#####################################\n");
printf("#Server Usage: #\n");
printf("#gcc server.c -o server #\n");
printf("#chmod 777 server #\n");
printf("#./server <ip> <port> #\n");
printf("# #\n");
printf("#<ip>:server ip:192.168.xx.xx #\n");
printf("#<port>:server port:1024~65535 #\n");
printf("#####################################\n");
return;
}
int main(int argc, char *argv[])
{
int listenfd = -1;
int connectfd = -1;
int ret;
int recv_bytes;
struct sockaddr_in serveraddr;
struct sockaddr_in clientaddr;
socklen_t peerlen;
char server_buf[BUFFER_SIZE] = {0};
char client_addr[IP_SIZE] = {0};
if (argc < 3) {
server_usage();
return SERVER_FAILURE;
}
/* socket */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd == -1) {
printf("[ERROR]server socket failed, why:%s\n", strerror(errno));
return SERVER_FAILURE;
}
printf("[DEBUG]server socket success, listenfd = %d\n", listenfd);
/* serveraddr */
memset(&serveraddr, 0x00, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[2]));
inet_pton(AF_INET, argv[1], &serveraddr.sin_addr);
/* bind */
ret = bind(listenfd, (const struct sockaddr *)&serveraddr, sizeof(serveraddr));
if (ret != 0) {
printf("[ERROR]server bind failed, why:%s\n", strerror(errno));
close(listenfd);
return SERVER_FAILURE;
}
printf("[DEBUG]server bind success\n");
/* listen */
ret = listen(listenfd, MAX_PENDDING_QUEUE);
if (ret != 0) {
printf("[ERROR]server listen failed, why:%s\n", strerror(errno));
close(listenfd);
return SERVER_FAILURE;
}
printf("[DEBUG]server listen success\n");
printf("server waiting for connect......\n\n");
/* accept */
while (true) {
memset(&clientaddr, 0x00, sizeof(clientaddr));
peerlen = sizeof(clientaddr);
connectfd = accept(listenfd, (struct sockaddr *)&clientaddr, &peerlen);
if (connectfd == -1) {
printf("[ERROR]server accept failed, why:%s\n", strerror(errno));
close(listenfd);
return SERVER_FAILURE;
}
memset(client_addr, 0x00, sizeof(client_addr));
inet_ntop(AF_INET, &clientaddr.sin_addr, client_addr, sizeof(client_addr));
printf("[DEBUG]server connected, client ip:%s, port:%d\n\n", client_addr, ntohs(clientaddr.sin_port));
/* send and recv */
while (true) {
memset(server_buf, 0x00, sizeof(server_buf));
printf("\033[1m<--- \033[0m"), fflush(stdout);
recv_bytes = recv(connectfd, server_buf, sizeof(server_buf), 0);
if (recv_bytes == -1) {
printf("[ERROR]server recv failed, why:%s\n", strerror(errno));
close(connectfd);
close(listenfd);
return SERVER_FAILURE;
} else if (recv_bytes == 0) {
printf("[DEBUG]server detected client gone!\n");
close(connectfd);
break;
}
printf("client@%s:%d said:%s\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), server_buf);
memset(server_buf, 0x00, sizeof(server_buf));
printf("\033[1m---> \033[0m"), fflush(stdout);
fgets(server_buf, sizeof(server_buf), stdin);
send(connectfd, server_buf, sizeof(server_buf), 0);
printf("\n");
}
}
close(listenfd);
return SERVER_SUCCESS;
}
client.c
/* client.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFFER_SIZE (1024)
#define CLIENT_SUCCESS (0)
#define CLIENT_FAILURE (-1)
#define MAX_PENDDING_QUEUE (10)
typedef enum {
false = 0,
true = 1,
} bool;
static void client_usage(void)
{
printf("#####################################\n");
printf("#Client Usage: #\n");
printf("#gcc client.c -o client #\n");
printf("#chmod 777 client #\n");
printf("#./client <ip> <port> #\n");
printf("# #\n");
printf("#<ip>:server ip:192.168.xx.xx #\n");
printf("#<port>:server port:1024~65535 #\n");
printf("#####################################\n");
return;
}
int main(int argc, char *argv[])
{
int sockfd = -1;
int ret;
int recv_bytes;
struct sockaddr_in serveraddr;
char client_buf[BUFFER_SIZE] = {0};
if (argc < 3) {
client_usage();
return CLIENT_FAILURE;
}
/* socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("[ERROR]client socket failed, why:%s\n", strerror(errno));
return CLIENT_FAILURE;
}
printf("[DEBUG]client socket success, sockfd = %d\n", sockfd);
/* serveraddr */
memset(&serveraddr, 0x00, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[2]));
inet_pton(AF_INET, argv[1], &serveraddr.sin_addr);
ret = connect(sockfd, (const struct sockaddr *)&serveraddr, sizeof(serveraddr));
if (ret == -1) {
printf("[ERROR]client connect failed, why:%s\n", strerror(errno));
close(sockfd);
return CLIENT_FAILURE;
}
printf("[DEBUG]client connect success\n");
while (true) {
memset(client_buf, 0x00, sizeof(client_buf));
printf("\033[1m---> \033[0m"), fflush(stdout);
fgets(client_buf, sizeof(client_buf), stdin);
printf("\n");
/* client said quit */
if (strncmp(client_buf, "quit!", strlen("quit!")) == 0) {
printf("[DEBUG]client said %s\n", client_buf);
break;
}
send(sockfd, client_buf, sizeof(client_buf), 0);
memset(client_buf, 0x00, sizeof(client_buf));
printf("\033[1m<--- \033[0m"), fflush(stdout);
recv_bytes = recv(sockfd, client_buf, sizeof(client_buf), 0);
if (recv_bytes == -1) {
printf("[ERROR]client recv failed, why:%s\n", strerror(errno));
close(sockfd);
return CLIENT_FAILURE;
} else if(recv_bytes == 0) {
printf("[DEBUG]client detected server gone!\n");
break;
}
printf("server@%s:%d said:%s\n", argv[1], atoi(argv[2]), client_buf);
}
close(sockfd);
printf("[DEBUG]<=====client exit\n");
return CLIENT_SUCCESS;
}
wireshark抓包结果:
2. 用原始套接字模拟ping操作并解析IP包与ICMP包
//This is a ping which can both send and receive ICMP packets
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/tcp.h>
#include <netinet/ip_icmp.h>
#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#define PING_SUCCESS (0)
#define PING_FAILURE (-1)
#define BUFFER_SIZE (1024)
#define MAGIC_NUM (3623)
//#define DEBUG
static unsigned short calc_cksum(unsigned short *addr, int len)
{
int sum=0;
unsigned short res=0;
while( len > 1) {
sum += *addr++;
len -= 2;
}
if( len == 1) {
*((unsigned char *)(&res))=*((unsigned char *)addr);
sum += res;
}
sum = (sum >>16) + (sum & 0xffff);
sum += (sum >>16) ;
res = ~sum;
return res;
}
int main(int argc, char *argv[])
{
if (argc < 4) {
printf("param error, usage: ./ping serverip -c <count>\n");
return PING_FAILURE;
}
int count = atoi(argv[3]);
char send_buff[BUFFER_SIZE] = {0};
char recv_buff[BUFFER_SIZE] = {0};
char src_buff[BUFFER_SIZE] = {0};
int sockfd = -1;
int recvfd = -1;
int ret, i, lenfrom;
struct sockaddr_in target_addr;
struct sockaddr_in source_addr;
/* socket */
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd == -1) {
printf("sockfd create for IPPROTO_ICMP failed, why:%s\n", strerror(errno));
return PING_FAILURE;
}
recvfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (recvfd == -1) {
printf("recvfd create for IPPROTO_ICMP failed, why:%s\n", strerror(errno));
close(sockfd);
return PING_FAILURE;
}
#ifdef DEBUG
printf("[DEBUG]socket create for IPPROTO_ICMP success\n");
#endif
memset(&target_addr, 0x00, sizeof(target_addr));
ret = inet_pton(AF_INET, argv[1], &target_addr.sin_addr);
if (ret != 1) {
printf("bad ip address to be converted:%s\n", argv[1]);
close(recvfd);
close(sockfd);
return PING_FAILURE;
}
struct icmp *picmp = (struct icmp *)send_buff;
struct ip *pip = (struct ip*)recv_buff;
struct icmp *p_recvicmp = (struct icmp *)(pip + 1);
for (i = 0; i < count; i++) {
memset(send_buff, 0x00, sizeof(send_buff));
/*----TYPE----CODE----CHECKSUM----
*----IDENTIFIER------SEQUENCE----
*----OPTION----------------------
*/
picmp->icmp_type = ICMP_ECHO; /* ECHO-REQUEST */
picmp->icmp_code = 0;
picmp->icmp_id = MAGIC_NUM;
picmp->icmp_seq = i;
picmp->icmp_cksum = calc_cksum((unsigned short *)picmp, 8);
/* PING REQUEST */
ret = sendto(sockfd, send_buff, 64, 0, (const struct sockaddr *)&target_addr, sizeof(target_addr)); /* ICMP total 64 bytes */
if (ret == -1) {
printf("turn %d sendto error, why:%s\n", i, strerror(errno));
close(recvfd);
close(sockfd);
return PING_FAILURE;
}
#ifdef DEBUG
printf("[DEBUG]turn %d, %d bytes send...\n", i, ret);
#endif
/* PING REPLY */
memset(recv_buff, 0x00, sizeof(recv_buff));
memset(&source_addr, 0x00, sizeof(source_addr));
lenfrom = sizeof(source_addr);
ret = recvfrom(sockfd, recv_buff, sizeof(recv_buff), 0, (struct sockaddr *)&source_addr, &lenfrom);
if (ret == -1) {
printf("turn %d recvfrom error, why:%s\n", i, strerror(errno));
close(recvfd);
close(sockfd);
return PING_FAILURE;
} else if (ret == 0) {
printf("turn %d detect socket peer shutdown!\n", i);
close(recvfd);
close(sockfd);
return PING_FAILURE;
}
#ifdef DEBUG
printf("[DEBUG]turn %d, %d bytes recv\n", i, ret);
printf("[DEBUG]recv ip header len = %d\n", pip->ip_hl);
#endif
if ((ret - (pip->ip_hl * 4)) < 8) { /* we assume ICMP at least 8 byte */
printf("turn %d no ICMP reply!\n", i);
close(recvfd);
close(sockfd);
return PING_FAILURE;
}
if ((p_recvicmp->icmp_type == ICMP_ECHOREPLY) && (p_recvicmp->icmp_id == MAGIC_NUM)) {
/* get the src and dst addr */
memset(src_buff, 0x00, sizeof(src_buff));
/* from where? */
inet_ntop(AF_INET, &source_addr.sin_addr, src_buff, sizeof(src_buff));
printf("[myping]%d bytes from %s to %s: icmp_seq=%u ttl=%d\n", (ret-(pip->ip_hl * 4)), (src_buff), (inet_ntoa(pip->ip_dst)), (p_recvicmp->icmp_seq), (pip->ip_ttl));
} else {
printf("[myping]recv no wanted packet!\n");
continue;
}
}
printf("done!\n");
close(recvfd);
close(sockfd);
return PING_SUCCESS;
}
wireshark抓包结果: