頭文件 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 MY_TCP 1
#define MY_UDP 2
typedef struct sockaddr* pSA; typedef struct sockaddr_in SA;
#define MY_ASSERT(flag,msg) ((flag)?NULL:(fprintf(stdout,msg),exit(EXIT_FAILURE)))
void my_socket(OUT int *sfd, int proto, char *ip, int port);
void my_listen(int sfd, int backlog);
void my_accept(OUT int *peer_sfd, int sfd, OUT pSA addr, IN_OUT int *len);
void my_connect(int sfd, char *peer_ip, int peer_port);
void my_recv(OUT int *len, int sfd, IN_OUT void *buf, int size);
void my_send(OUT int *len, int sfd, void *buf, int size);
void my_recvfrom(OUT int *len, int sfd, IN_OUT void *buf, int size, OUT char* ip, OUT int* port);
void my_sendto(OUT int *len, int sfd, void *buf, int size, char *ip, int port);
void my_close(int sfd);
#endif
核心實現 my_socket.c
my_socket():創建 socket、設置 SO_REUSEADDR、綁定本地 IP/端口。
my_connect():最多重試 10 次,間隔 1s。
my_recv/send():循環收發直到滿足長度,處理短讀寫。
my_recvfrom/sendto():UDP 專用,自動解析/填充對端地址。
測試服務端 server.c
my_socket(&fd_server, MY_TCP, IP, PORT);
my_listen(fd_server, 5);
my_accept(&fd_client, fd_server, NULL, NULL);
while(1) {
my_recv(&len, fd_client, &val, sizeof(val));
my_send(&len, fd_client, &val, sizeof(val));
}
測試客戶端 client.c
my_socket(&fd_client, MY_TCP, IP, MY_PORT);
my_connect(fd_client, IP, SERVER_PORT);
while(scanf("%d", &val_in)==1) {
my_send(NULL, fd_client, &val_in, sizeof(val_in));
my_recv(NULL, fd_client, &val_out, sizeof(val_out));
}
動態庫生成與使用
gcc -fPIC -shared my_socket.c -o libmysocket.so
gcc server.c -L. -lmysocket -o server
gcc client.c -L. -lmysocket -o client
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
關鍵優化
- 統一錯誤處理宏
MY_ASSERT。
- 收發循環保證數據完整性。
- TCP/UDP 介面一致,業務層無感切換。