套接字(socket)为通信的端点,每个套接字由一个 IP 地址和一个端口号组成。通过网络通信的每对进程需要使用一对套接字,即每个进程各有一个;
😇通用代码封装
/*socket_wrap.h*/
#ifndef __SOCKET_WRAP_H_
#define __SOCKET_WRAP_H_
int Socket_Wrap(int domain,int type,int protocol);
int TCP_Socket_Wrap(void);
int UDP_Socket_Wrap(void);
int Bind_Wrap(int sockfd,const char *ip,int port);
int Listen_Wrap(int sockfd,int backlog);
int Accept_Wrap(int sockfd, struct sockaddr *cli_addr, socklen_t *cli_addrlen);
int Connect_Wrap(int cli_sockfd,const char *serv_ip,int serv_port);
int Setsockopt_Wrap(int sockfd,int level,int optname,
const void *optval, socklen_t optlen);
int Setsock_Nonblock(int sockfd);
int New_TCP_ServSocket(const char *ip,int port);
int New_UDP_ServSocket(const char *ip,int port);
#endif
/*socket_wrap.c*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>
#include <fcntl.h>
void Socket_Error(const char *info)
{
perror(info);
}
int Socket_Wrap(int domain,int type,int protocol)
{
int listen_socket;
if((listen_socket = socket(domain,type,protocol)) < 0)
{
Socket_Error("socket");
}
return listen_socket;
}
int TCP_Socket_Wrap(void)
{
int listen_socket;
if((listen_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
{
Socket_Error("tcp socket");
}
return listen_socket;
}
int UDP_Socket_Wrap(void)
{
int listen_socket;
if((listen_socket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
{
Socket_Error("udp socket");
}
return listen_socket;
}
//int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
int Bind_Wrap(int sockfd,const char *ip,int port)
{
int ret;
struct sockaddr_in serv_addr;
socklen_t serv_addrlen;
serv_addrlen = sizeof(struct sockaddr_in);
bzero(&serv_addr,serv_addrlen);
serv_addr.sin_family = AF_INET;
ret = inet_pton(AF_INET, ip, &serv_addr.sin_addr.s_addr);
if(ret == 0 || errno == EAFNOSUPPORT)
{
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
serv_addr.sin_port = htons(port);
if((ret = bind(sockfd,(struct sockaddr *)&serv_addr,serv_addrlen)) < 0)
{
Socket_Error("bind");
}
return ret;
}
//int listen(int sockfd, int backlog);
int Listen_Wrap(int sockfd,int backlog)
{
int ret;
if((ret = listen(sockfd,backlog)) < 0)
{
Socket_Error("listen");
}
return ret;
}
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int Accept_Wrap(int sockfd, struct sockaddr *cli_addr, socklen_t *cli_addrlen)
{
int accept_socket;
retry:
if ((accept_socket = accept(sockfd, cli_addr, cli_addrlen)) < 0) {
if ((errno == ECONNABORTED) || (errno == EINTR))
goto retry;
else
Socket_Error("accept");
}
return accept_socket;
}
//客户端
//int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
int Connect_Wrap(int cli_sockfd,const char *serv_ip,int serv_port)
{
int ret;
struct sockaddr_in serv_addr;
socklen_t serv_addrlen;
serv_addrlen = sizeof(struct sockaddr_in);
bzero(&serv_addr,serv_addrlen);
serv_addr.sin_family = AF_INET;
ret = inet_pton(AF_INET, serv_ip, &serv_addr.sin_addr.s_addr);
if(ret == 0 || errno == EAFNOSUPPORT)
{
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
serv_addr.sin_port = htons(serv_port);
if((ret = connect(cli_sockfd,(struct sockaddr *)&serv_addr,serv_addrlen)) < 0)
{
Socket_Error("connect");
}
return ret;
}
//setsockopt
//int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
int Setsockopt_Wrap(int sockfd,int level,int optname,const void *optval, socklen_t optlen)
{
int ret;
if((ret = setsockopt(sockfd,level,optname,optval,optlen)) < 0)
{
Socket_Error("setsockopt");
}
return ret;
}
//setsocknonblock
int Setsock_Nonblock(int sockfd)
{
int flag,ret;
flag = fcntl(sockfd,F_GETFL);
flag |= O_NONBLOCK;
if((ret = fcntl(sockfd,F_SETFL,flag)) < 0)
{
Socket_Error("fcntl");
}
return ret;
}
//TCP
int New_TCP_ServSocket(const char *ip,int port)
{
int listen_socket,on;
if((listen_socket = TCP_Socket_Wrap()) < 0)
{
return -1;
}
//端口复用
on = 1;
if(Setsockopt_Wrap(listen_socket,SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
{
return -2;
}
if(Bind_Wrap(listen_socket,ip,port) < 0)
{
return -3;
}
if(Listen_Wrap(listen_socket,20) < 0)
{
return -4;
}
return listen_socket;
}
//UDP
int New_UDP_ServSocket(const char *ip,int port)
{
int listen_socket,on;
if((listen_socket = UDP_Socket_Wrap()) < 0)
{
return -1;
}
//端口复用
on = 1;
if(Setsockopt_Wrap(listen_socket,SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
{
return -2;
}
if(Bind_Wrap(listen_socket,ip,port) < 0)
{
return -3;
}
#if 0 //无效
if(Listen_Wrap(listen_socket,20) < 0)
{
return -4;
}
#endif
return listen_socket;
}
👉TCP测试demo
/*tcp_server.c*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include "socket_wrap.h"
//C/S模型
//S端
#define SERV_IP "127.0.0.1"
#define SERV_PORT 4567
int main(void)
{
int serv_sockfd,accept_sockfd;
struct sockaddr_in cli_addr;
socklen_t cli_addrlen;
serv_sockfd = New_TCP_ServSocket(SERV_IP,SERV_PORT);
if(serv_sockfd < 0)
{
return -1;
}
cli_addrlen = sizeof(struct sockaddr_in);
accept_sockfd = Accept_Wrap(serv_sockfd, (struct sockaddr *)&cli_addr, &cli_addrlen);
if(accept_sockfd< 0)
{
return -2;
}
char buf[1024] = {0};
ssize_t recv_len = 0;
ssize_t send_len = 0;
int i = 0;
while(1)
{
bzero(buf,sizeof(buf));
recv_len = recv(accept_sockfd, buf, sizeof(buf), 0);
if(recv_len < 0)
{
printf("recv fail\n");
break;
}
else if(recv_len == 0)//对端关闭
{
continue;
}
printf("recv_len =%d\n",recv_len);
write(STDOUT_FILENO, buf, recv_len);
//字符小写转大写
for(i = 0; i < recv_len; i++)
{
buf[i] = toupper(buf[i]);
}
send_len = send(accept_sockfd, buf, recv_len, 0);
if(send_len < 0)
{
printf("send fail\n");
}
}
close(accept_sockfd);
close(serv_sockfd);
}
/*tcp_client.c*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "socket_wrap.h"
//C/S模型
//C端
#define SERV_IP "127.0.0.1"
#define SERV_PORT 4567
int main(void)
{
int cli_sockfd,ret;
cli_sockfd = TCP_Socket_Wrap();
if(cli_sockfd < 0)
{
return -1;
}
ret = Connect_Wrap(cli_sockfd,SERV_IP,SERV_PORT);
if(ret < 0)
{
return -2;
}
char buf[1024] = {0};
ssize_t recv_len = 0;
ssize_t send_len = 0;
while(1)
{
/*从标准输入获取数据*/
bzero(buf,sizeof(buf));
fgets(buf, sizeof(buf), stdin);
//写到服务器端
send_len = send(cli_sockfd, buf, sizeof(buf), 0);
if(send_len < 0)
{
printf("send fail\n");
}
//读数据
recv_len = recv(cli_sockfd, buf, sizeof(buf), 0);
if(recv_len < 0)
{
printf("recv fail\n");
}
/*写至标准输出*/
write(STDOUT_FILENO, buf, recv_len);
}
close(cli_sockfd);
}