国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Linux > 正文

Linux網(wǎng)絡(luò)編程8——對TCP與UDP的簡易封裝

2024-06-28 13:24:22
字體:
供稿:網(wǎng)友
linux網(wǎng)絡(luò)編程8——對TCP與UDP的簡易封裝引言

每次使用socket通信,都會有很對相似的操作。本文,會對TCP與UDP通信做一簡單封裝,并生成動態(tài)庫。

代碼

my_socket.h

#ifndef __MY_SOCKET_H__#define __MY_SOCKET_H__#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#define IN#define OUT#define IN_OUT#define MY_TCP 1#define MY_UDP 2typedef struct sockaddr* pSA ;typedef struct sockaddr_in SA ;#define MY_ASSERT(flag,msg) ( (flag) ? NULL : ( fPRintf(stdout,msg), exit(EXIT_FAILURE) ) )   // NULL代表什么也不做void my_socket(OUT int *local_sfd, int protocal, char *local_ip, int local_port);void my_listen(int local_sfd, int backlog);void my_accept(OUT int *peer_sfd, int local_sfd, OUT pSA peer_addr, IN_OUT int *addr_len );void my_connect(int local_sfd, pSA peer_addr, int addr_len);void my_recv(OUT int *recv_len, int peer_sfd, IN_OUT void *base, int len);void my_send(OUT int *send_len, int peer_sfd, void *base, int len);void my_recvfrom(OUT int *recvfrom_len, int peer_sfd, IN_OUT void *base, int len, OUT pSA peer_addr, IN_OUT int *addr_len);void my_sendto(OUT int *sendto_len, int peer_sfd, OUT void *base, int len,  pSA peer_addr, int addr_len);void my_close(int sfd);#endif

my_socket.c

/*************************************************************************    > File Name: my_socket.c    > Author: KrisChou    > Mail:zhoujx0219@163.com     > Created Time: Mon 01 Sep 2014 06:54:48 PM CST ************************************************************************//* 本代碼用于在一臺主機(jī)上模擬socket通信。因此IP地址對于server和client而言是一樣的。 * 為了簡化代碼,此處即使是客戶端,也提前分配好端口號。事實(shí)上,主動方的端口號可以由系統(tǒng)分配,不用提前綁定 * --> 無論server或者client,都會預(yù)先綁定本地socket *//* 本代碼local_sfd代表本地socket描述符。 * 對于服務(wù)器而言,就是用于監(jiān)聽的socket; 對于客戶端而言就是用于通信的socket * peer_sfd,代表與對方通信的socket描述符。 * 對于服務(wù)器而言,由accept以傳出參數(shù)形式返回;對于客戶端而言,就是本地socket */#include "my_socket.h"void my_socket(OUT int *local_sfd, int protocal, char *local_ip, int local_port){    MY_ASSERT(protocal == MY_TCP || protocal == MY_UDP, "wrong arg! protocal is MY_TCP or MY_UDP! /n");    /* 創(chuàng)建本地socket */    if(protocal == MY_TCP)    {        MY_ASSERT(-1 != (*local_sfd = socket(AF_INET, SOCK_STREAM, 0)), "tcp_socket init falure!/n");    }else if(protocal == MY_UDP)    {        MY_ASSERT(-1 != (*local_sfd = socket(AF_INET, SOCK_DGRAM, 0)),  "udp_socket init failure!/n");    }    /* 將本地聯(lián)系方式bind到本地socket */    SA local_addr;    memset(&local_addr, 0, sizeof(SA));    local_addr.sin_family      = AF_INET;    local_addr.sin_port        = htons(local_port);    local_addr.sin_addr.s_addr = inet_addr(local_ip);    MY_ASSERT( 0 == bind(*local_sfd, (pSA)&local_addr, sizeof(SA)), "bind failure!/n");}/*----------------------------- 以下針對TCP ----------------------------------------------------- *//* server: listen + accept */void my_listen(int local_sfd, int backlog){    MY_ASSERT( 0 == listen(local_sfd, backlog), "listen failure!/n");}void my_accept(OUT int *peer_sfd, int local_sfd, OUT pSA peer_addr, IN_OUT int *addr_len ){    MY_ASSERT(-1 != (*peer_sfd = accept(local_sfd, peer_addr, addr_len)), "accept failure!/n");}/* client: connect */void my_connect(int local_sfd, pSA peer_addr, int addr_len){    int cnt = 0;    // 10次連不上就退出程序    while(-1 == connect(local_sfd, peer_addr, addr_len))    {        cnt++;        if(cnt == 10)        {            printf("connect failure!/n");            exit(EXIT_FAILURE);        }        sleep(1);    }}/* recv and send */void my_recv(OUT int *recv_len, int peer_sfd, IN_OUT void *base, int len){    MY_ASSERT(-1 != (*recv_len = recv(peer_sfd, base, len, 0)), "recv error! /n");}void my_send(OUT int *send_len, int peer_sfd, void *base, int len){    MY_ASSERT(-1 != (*send_len = send(peer_sfd, base, len, 0)), "send error! /n");}/*---------------------------- 以下針對UDP--------------------------------------------------------*/void my_recvfrom(OUT int *recvfrom_len, int peer_sfd, IN_OUT void *base, int len, OUT pSA peer_addr, IN_OUT int *addr_len){    MY_ASSERT(-1 != (*recvfrom_len = recvfrom(peer_sfd, base, len, 0, peer_addr, addr_len)), "recvfrom failure!/n");}void my_sendto(OUT int *sendto_len, int peer_sfd, OUT void *base, int len,  pSA peer_addr, int addr_len){    MY_ASSERT(-1 != (*sendto_len = sendto(peer_sfd, base, len, 0, peer_addr, addr_len)), "sendto failure!/n");}/* close */void my_close(int sfd){    MY_ASSERT(0 == close(sfd), "close failure!/n");}
生成動態(tài)庫
gcc -fPIC -o my_socket.o -c my_socket.c         //我的.h文件和.c文件在一個(gè)目錄下,如果不在,請指定頭文件位置gcc -shared -o libmy_socket.so.1.0 my_socket.o    cp./libmy_socket.s0.1.0 /libcd /libln -s libmy_socket.so.1.0 libmy_socket.so

我個(gè)人將頭文件放在主目錄的include文件夾下,方便以后查找和使用。(/home/purple/include)

測試代碼

server.c

#include "my_socket.h"#define IP "192.168.153.128"#define PORT 8888int main(int argc, char *argv[]){    int fd_server, fd_client;    int val;  //用4個(gè)字節(jié)的地址空間來傳數(shù)據(jù)    int len;    my_socket(&fd_server, MY_TCP, IP, PORT);    my_listen(fd_server,5);    my_accept(&fd_client, fd_server, NULL, NULL);    printf("accept success!/n");    while(1)    {        my_recv(&len, fd_client, (void*)&val, sizeof(val));        printf("recv data: %d/n", val);        my_send(&len, fd_client, (void*)&val, sizeof(val));        printf("%d has sent!/n/n", val);    }    my_close(fd_client);    my_close(fd_server);    return 0;}

client.c

#include "my_socket.h"#define IP "192.168.153.128"#define MY_PORT 6666#define SERVER_PORT 8888int main(int argc, char *argv[]){    /* socket */    int fd_client;    my_socket(&fd_client, MY_TCP, IP, MY_PORT);        /* connect */    SA server_addr;    memset(&server_addr,0,sizeof(server_addr));    server_addr.sin_family = AF_INET;    server_addr.sin_port = htons(SERVER_PORT);    server_addr.sin_addr.s_addr = inet_addr(IP);        my_connect(fd_client, (pSA)&server_addr, sizeof(SA));    printf("connect success!/n");        /* 發(fā)送一個(gè)數(shù)據(jù),并從服務(wù)器端返回這個(gè)數(shù)據(jù) */    int val_in,val_out,len;    while(scanf("%d", &val_in) == 1)    {        my_send(&len,fd_client,(void*)&val_in,sizeof(int));        my_recv(&len,fd_client,(void*)&val_out,sizeof(int));        printf("recv fron server: %d/n", val_out);    }        my_close(fd_client);    return 0;    }

編譯如下

gcc -o server server.c -lmy_socket -I/home/purple/includegcc -o client client.c -lmy_socket -I/home/purple/include

經(jīng)測試沒有問題。

注意

短路運(yùn)算(||)必須有返回值,而exit返回值為void,因此頭文件中的宏定義,我們沒有使用短路運(yùn)算,而是使用了三目運(yùn)算符。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 江津市| 卓尼县| 安新县| 栾城县| 盐城市| 阿城市| 太原市| 石景山区| 北辰区| 南陵县| 于田县| 肃北| 万盛区| 延吉市| 同江市| 抚宁县| 清徐县| 阳西县| 怀集县| 仲巴县| 叙永县| 敖汉旗| 铜梁县| 特克斯县| 山丹县| 洛阳市| 江城| 深水埗区| 米泉市| 富顺县| 安陆市| 云安县| 仙桃市| 苏尼特左旗| 苗栗市| 延川县| 涿州市| 吴江市| 临朐县| 巨野县| 沅江市|