先附上代码:
server:
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
int main(int argc,char** argv)
{
int fd,newfd;
int ret;
char buf[32]={0};
struct sockaddr_in addr;
if(argc<3)
{
fprintf(stderr, "%s <addr><port>\n",argv[0]);
exit(0);
}
fd=socket(AF_INET,SOCK_STREAM,0);//创建套接字
if(fd<0)
{
perror("socket");
return -1;
}
addr.sin_family=AF_INET;
addr.sin_port=htons(atoi(argv[2]));//将字符串转换为端口号
if (inet_aton(argv[1], &addr.sin_addr) == 0) {
fprintf(stderr, "Invalid address\n");
exit(EXIT_FAILURE);
}//将字符串转换为二进制的网络字节序
ret=bind(fd,(struct sockaddr *) &addr, sizeof(addr));//绑定ip
if(ret==-1)
{
perror("bind");
return -1;
}
ret=listen(fd,5);
if(ret==-1)
{
perror("listen");
return -1;
}
newfd=accept(fd,NULL,NULL);
if(newfd<0)
{
perror("accept");
return -1;
}
while(1)
{
memset(buf,0,sizeof(buf));
ret=read(newfd,buf,sizeof(buf));//从客户端读取
if(ret<0)
{
perror("read");
exit(0);
}
else if(ret==0)
{
break;
}
else if(ret>0)
{
printf("%s\n",buf);
}
}
close(newfd);
close(fd);
return 0;
}
client:
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <signal.h>
void handler(int arg)
{
printf("close");
}
int main(int argc, char **argv)
{
int fd;
int ret;
char buf[32];
struct sigaction act;
struct sockaddr_in addr;
if(argc<3)
{
fprintf(stderr, "%s <addr><port>\n",argv[0]);
exit(0);
}
act.sa_flags=0;
act.sa_handler=handler;
sigemptyset(&act.sa_mask);
ret=sigaction(SIGPIPE, &act,NULL);//信号捕捉,验证读端关闭时,写端会收到SIGPIPE信号
fd=socket(AF_INET,SOCK_STREAM,0);
if(fd<0)
{
perror("socket");
return -1;
}
addr.sin_family=AF_INET;
addr.sin_port=htons(atoi(argv[2]));
if (inet_aton(argv[1], &addr.sin_addr) == 0) {
fprintf(stderr, "Invalid address\n");
exit(EXIT_FAILURE);
}
ret=connect(fd,(struct sockaddr *) &addr, sizeof(addr));//与服务器建立连接,服务端没打开无法建立连接
if(ret==-1)
{
perror("connect");
return -1;
}
while(1)
{
printf(">>");
fgets(buf,32,stdin);
ret=write(fd,buf,sizeof(buf));
}
close(fd);
return 0;
}
本代码实现套接字通信,分为服务器端和写端,其中还包含信号捕捉来验证当读端退出时,写端还往读端写入数据就会收到SIGPIPE信号。
值得注意的是:
1.socket函数返回的是文件描述符,linux下一切皆文件
2.accept函数会返回新的文件描述符,给read、write等函数使用
3.accept中的参数结构体与bind中的参数结构体不一致,accept中的结构体是客户端的结构体
4.套接字连接的全双工的通道