Linux下TCP Socket编程C语言小实例
2013-03-23 23:33
447 查看
TCPServer端
[cpp]
view plaincopyprint?
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <memory.h>
#include <unistd.h>
//#include <linux/in.h>
#include <netinet/in.h>
//#include <linux/inet_diag.h>
#include <arpa/inet.h>
#include <signal.h>
/**
关于 sockaddr sockaddr_in socketaddr_un说明 http://maomaozaoyue.blog.sohu.com/197538359.html */
#define PORT 11910 //定义通信端口
#define BACKLOG 5 //定义侦听队列长度
#define buflen 1024
void process_conn_server(int s);
void sig_pipe(int signo);
int ss,sc; //ss为服务器socket描述符,sc为某一客户端通信socket描述符
int main(int argc,char *argv[])
{
struct sockaddr_in server_addr; //存储服务器端socket地址结构
struct sockaddr_in client_addr; //存储客户端 socket地址结构
int err; //返回值
pid_t pid; //分叉进行的ID
/*****************socket()***************/
ss = socket(AF_INET,SOCK_STREAM,0); //建立一个序列化的,可靠的,双向连接的的字节流
if(ss<0)
{
printf("server : server socket create error\n");
return -1;
}
//注册信号
sighandler_t ret;
ret = signal(SIGTSTP,sig_pipe);
if(SIG_ERR == ret)
{
printf("信号挂接失败\n");
return -1;
}
else
printf("信号挂接成功\n");
/******************bind()****************/
//初始化地址结构
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET; //协议族
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //本地地址
server_addr.sin_port = htons(PORT);
err = bind(ss,(struct sockaddr *)&server_addr,sizeof(sockaddr));
if(err<0)
{
printf("server : bind error\n");
return -1;
}
/*****************listen()***************/
err = listen(ss,BACKLOG); //设置监听的队列大小
if(err < 0)
{
printf("server : listen error\n");
return -1;
}
/****************accept()***************/
/**
为类方便处理,我们使用两个进程分别管理两个处理:
1,服务器监听新的连接请求;2,以建立连接的C/S实现通信
这两个任务分别放在两个进程中处理,为了防止失误操作
在一个进程中关闭 侦听套接字描述符 另一进程中关闭
客户端连接套接字描述符。注只有当所有套接字全都关闭时
当前连接才能关闭,fork调用的时候父进程与子进程有相同的
套接字,总共两套,两套都关闭掉才能关闭这个套接字
*/
for(;;)
{
socklen_t addrlen = sizeof(client_addr);
//accept返回客户端套接字描述符
sc = accept(ss,(struct sockaddr *)&client_addr,&addrlen); //注,此处为了获取返回值使用 指针做参数
if(sc < 0) //出错
{
continue; //结束此次循环
}
else
{
printf("server : connected\n");
}
//创建一个子线程,用于与客户端通信
pid = fork();
//fork 调用说明:子进程返回 0 ;父进程返回子进程 ID
if(pid == 0) //子进程,与客户端通信
{
close(ss);
process_conn_server(sc);
}
else
{
close(sc);
}
}
}
/**
服务器对客户端连接处理过程;先读取从客户端发送来的数据,
然后将接收到的数据的字节的个数发送到客户端
*/
//通过套接字 s 与客户端进行通信
void process_conn_server(int s)
{
ssize_t size = 0;
char buffer[buflen]; //定义数据缓冲区
for(;;)
{
//等待读
for(size = 0;size == 0 ;size = read(s,buffer,buflen));
//输出从客户端接收到的数据
printf("%s",buffer);
//结束处理
if(strcmp(buffer,"quit") == 0)
{
close(s); //成功返回0,失败返回-1
return ;
}
sprintf(buffer,"%d bytes altogether\n",size);
write(s,buffer,strlen(buffer)+1);
}
}
void sig_pipe(int signo)
{
printf("catch a signal\n");
if(signo == SIGTSTP)
{
printf("接收到 SIGTSTP 信号\n");
int ret1 = close(ss);
int ret2 = close(sc);
int ret = ret1>ret2?ret1:ret2;
if(ret == 0)
printf("成功 : 关闭套接字\n");
else if(ret ==-1 )
printf("失败 : 未关闭套接字\n");
exit(1);
}
}
TCPClient端
[cpp]
view plaincopyprint?
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <stdlib.h>
#include <memory.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <signal.h> //添加信号处理 防止向已断开的连接通信
/**
信号处理顺序说明:在Linux操作系统中某些状况发生时,系统会向相关进程发送信号,
信号处理方式是:1,系统首先调用用户在进程中注册的函数,2,然后调用系统的默认
响应方式,此处我们可以注册自己的信号处理函数,在连接断开时执行
*/
#define PORT 11910
#define Buflen 1024
void process_conn_client(int s);
void sig_pipe(int signo); //用户注册的信号函数,接收的是信号值
int s; //全局变量 , 存储套接字描述符
int main(int argc,char *argv[])
{
sockaddr_in server_addr;
int err;
sighandler_t ret;
char server_ip[50] = "";
/********************socket()*********************/
s= socket(AF_INET,SOCK_STREAM,0);
if(s<0)
{
printf("client : create socket error\n");
return 1;
}
//信号处理函数 SIGINT 是当用户按一个 Ctrl-C 建时发送的信号
ret = signal(SIGTSTP,sig_pipe);
if(SIG_ERR == ret)
{
printf("信号挂接失败\n");
return -1;
}
else
printf("信号挂接成功\n") ;
/*******************connect()*********************/
//设置服务器地址结构,准备连接到服务器
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
/*将用户数入对额字符串类型的IP格式转化为整型数据*/
//inet_pton(AF_INET,argv[1],&server_addr.sin_addr.s_addr);
printf("please input server ip address : \n");
read(0,server_ip,50);
//err = inet_pton(AF_INET,server_ip,&server_addr.sin_addr.s_addr);
server_addr.sin_addr.s_addr = inet_addr(server_ip);
err = connect(s,(struct sockaddr *)&server_addr,sizeof(sockaddr));
if(err == 0)
{
printf("client : connect to server\n");
}
else
{
printf("client : connect error\n");
return -1;
}
//与服务器端进行通信
process_conn_client(s);
close(s);
}
void process_conn_client(int s)
{
ssize_t size = 0;
char buffer[Buflen];
for(;;)
{
memset(buffer,'\0',Buflen);
/*从标准输入中读取数据放到缓冲区buffer中*/
size = read(0,buffer,Buflen); // 0,被默认的分配到标准输入 1,标准输出 2,error
if(size > 0)
{
//当向服务器发送 “quit” 命令时,服务器首先断开连接
write(s,buffer,strlen(buffer)+1); //向服务器端写
//等待读取到数据
for(size = 0 ; size == 0 ; size = read(s,buffer,Buflen) );
write(1,buffer,strlen(buffer)+1); //向标准输出写
}
}
}
void sig_pipe(int signo) //传入套接字描述符
{
printf("Catch a signal\n");
if(signo == SIGTSTP)
{
printf("接收到 SIGTSTP 信号\n");
int ret = close(s);
if(ret == 0)
printf("成功 : 关闭套接字\n");
else if(ret ==-1 )
printf("失败 : 未关闭套接字\n");
exit(1);
}
}
运行结果
TCPServer端
TCPClient端
netstat查看网络连接
[cpp]
view plaincopyprint?
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <memory.h>
#include <unistd.h>
//#include <linux/in.h>
#include <netinet/in.h>
//#include <linux/inet_diag.h>
#include <arpa/inet.h>
#include <signal.h>
/**
关于 sockaddr sockaddr_in socketaddr_un说明 http://maomaozaoyue.blog.sohu.com/197538359.html */
#define PORT 11910 //定义通信端口
#define BACKLOG 5 //定义侦听队列长度
#define buflen 1024
void process_conn_server(int s);
void sig_pipe(int signo);
int ss,sc; //ss为服务器socket描述符,sc为某一客户端通信socket描述符
int main(int argc,char *argv[])
{
struct sockaddr_in server_addr; //存储服务器端socket地址结构
struct sockaddr_in client_addr; //存储客户端 socket地址结构
int err; //返回值
pid_t pid; //分叉进行的ID
/*****************socket()***************/
ss = socket(AF_INET,SOCK_STREAM,0); //建立一个序列化的,可靠的,双向连接的的字节流
if(ss<0)
{
printf("server : server socket create error\n");
return -1;
}
//注册信号
sighandler_t ret;
ret = signal(SIGTSTP,sig_pipe);
if(SIG_ERR == ret)
{
printf("信号挂接失败\n");
return -1;
}
else
printf("信号挂接成功\n");
/******************bind()****************/
//初始化地址结构
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET; //协议族
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //本地地址
server_addr.sin_port = htons(PORT);
err = bind(ss,(struct sockaddr *)&server_addr,sizeof(sockaddr));
if(err<0)
{
printf("server : bind error\n");
return -1;
}
/*****************listen()***************/
err = listen(ss,BACKLOG); //设置监听的队列大小
if(err < 0)
{
printf("server : listen error\n");
return -1;
}
/****************accept()***************/
/**
为类方便处理,我们使用两个进程分别管理两个处理:
1,服务器监听新的连接请求;2,以建立连接的C/S实现通信
这两个任务分别放在两个进程中处理,为了防止失误操作
在一个进程中关闭 侦听套接字描述符 另一进程中关闭
客户端连接套接字描述符。注只有当所有套接字全都关闭时
当前连接才能关闭,fork调用的时候父进程与子进程有相同的
套接字,总共两套,两套都关闭掉才能关闭这个套接字
*/
for(;;)
{
socklen_t addrlen = sizeof(client_addr);
//accept返回客户端套接字描述符
sc = accept(ss,(struct sockaddr *)&client_addr,&addrlen); //注,此处为了获取返回值使用 指针做参数
if(sc < 0) //出错
{
continue; //结束此次循环
}
else
{
printf("server : connected\n");
}
//创建一个子线程,用于与客户端通信
pid = fork();
//fork 调用说明:子进程返回 0 ;父进程返回子进程 ID
if(pid == 0) //子进程,与客户端通信
{
close(ss);
process_conn_server(sc);
}
else
{
close(sc);
}
}
}
/**
服务器对客户端连接处理过程;先读取从客户端发送来的数据,
然后将接收到的数据的字节的个数发送到客户端
*/
//通过套接字 s 与客户端进行通信
void process_conn_server(int s)
{
ssize_t size = 0;
char buffer[buflen]; //定义数据缓冲区
for(;;)
{
//等待读
for(size = 0;size == 0 ;size = read(s,buffer,buflen));
//输出从客户端接收到的数据
printf("%s",buffer);
//结束处理
if(strcmp(buffer,"quit") == 0)
{
close(s); //成功返回0,失败返回-1
return ;
}
sprintf(buffer,"%d bytes altogether\n",size);
write(s,buffer,strlen(buffer)+1);
}
}
void sig_pipe(int signo)
{
printf("catch a signal\n");
if(signo == SIGTSTP)
{
printf("接收到 SIGTSTP 信号\n");
int ret1 = close(ss);
int ret2 = close(sc);
int ret = ret1>ret2?ret1:ret2;
if(ret == 0)
printf("成功 : 关闭套接字\n");
else if(ret ==-1 )
printf("失败 : 未关闭套接字\n");
exit(1);
}
}
#include <stdio.h> #include <stdlib.h> #include <strings.h> #include <sys/types.h> #include <sys/socket.h> #include <memory.h> #include <unistd.h> //#include <linux/in.h> #include <netinet/in.h> //#include <linux/inet_diag.h> #include <arpa/inet.h> #include <signal.h> /** 关于 sockaddr sockaddr_in socketaddr_un说明 http://maomaozaoyue.blog.sohu.com/197538359.html */ #define PORT 11910 //定义通信端口 #define BACKLOG 5 //定义侦听队列长度 #define buflen 1024 void process_conn_server(int s); void sig_pipe(int signo); int ss,sc; //ss为服务器socket描述符,sc为某一客户端通信socket描述符 int main(int argc,char *argv[]) { struct sockaddr_in server_addr; //存储服务器端socket地址结构 struct sockaddr_in client_addr; //存储客户端 socket地址结构 int err; //返回值 pid_t pid; //分叉进行的ID /*****************socket()***************/ ss = socket(AF_INET,SOCK_STREAM,0); //建立一个序列化的,可靠的,双向连接的的字节流 if(ss<0) { printf("server : server socket create error\n"); return -1; } //注册信号 sighandler_t ret; ret = signal(SIGTSTP,sig_pipe); if(SIG_ERR == ret) { printf("信号挂接失败\n"); return -1; } else printf("信号挂接成功\n"); /******************bind()****************/ //初始化地址结构 memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family = AF_INET; //协议族 server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //本地地址 server_addr.sin_port = htons(PORT); err = bind(ss,(struct sockaddr *)&server_addr,sizeof(sockaddr)); if(err<0) { printf("server : bind error\n"); return -1; } /*****************listen()***************/ err = listen(ss,BACKLOG); //设置监听的队列大小 if(err < 0) { printf("server : listen error\n"); return -1; } /****************accept()***************/ /** 为类方便处理,我们使用两个进程分别管理两个处理: 1,服务器监听新的连接请求;2,以建立连接的C/S实现通信 这两个任务分别放在两个进程中处理,为了防止失误操作 在一个进程中关闭 侦听套接字描述符 另一进程中关闭 客户端连接套接字描述符。注只有当所有套接字全都关闭时 当前连接才能关闭,fork调用的时候父进程与子进程有相同的 套接字,总共两套,两套都关闭掉才能关闭这个套接字 */ for(;;) { socklen_t addrlen = sizeof(client_addr); //accept返回客户端套接字描述符 sc = accept(ss,(struct sockaddr *)&client_addr,&addrlen); //注,此处为了获取返回值使用 指针做参数 if(sc < 0) //出错 { continue; //结束此次循环 } else { printf("server : connected\n"); } //创建一个子线程,用于与客户端通信 pid = fork(); //fork 调用说明:子进程返回 0 ;父进程返回子进程 ID if(pid == 0) //子进程,与客户端通信 { close(ss); process_conn_server(sc); } else { close(sc); } } } /** 服务器对客户端连接处理过程;先读取从客户端发送来的数据, 然后将接收到的数据的字节的个数发送到客户端 */ //通过套接字 s 与客户端进行通信 void process_conn_server(int s) { ssize_t size = 0; char buffer[buflen]; //定义数据缓冲区 for(;;) { //等待读 for(size = 0;size == 0 ;size = read(s,buffer,buflen)); //输出从客户端接收到的数据 printf("%s",buffer); //结束处理 if(strcmp(buffer,"quit") == 0) { close(s); //成功返回0,失败返回-1 return ; } sprintf(buffer,"%d bytes altogether\n",size); write(s,buffer,strlen(buffer)+1); } } void sig_pipe(int signo) { printf("catch a signal\n"); if(signo == SIGTSTP) { printf("接收到 SIGTSTP 信号\n"); int ret1 = close(ss); int ret2 = close(sc); int ret = ret1>ret2?ret1:ret2; if(ret == 0) printf("成功 : 关闭套接字\n"); else if(ret ==-1 ) printf("失败 : 未关闭套接字\n"); exit(1); } }
TCPClient端
[cpp]
view plaincopyprint?
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <stdlib.h>
#include <memory.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <signal.h> //添加信号处理 防止向已断开的连接通信
/**
信号处理顺序说明:在Linux操作系统中某些状况发生时,系统会向相关进程发送信号,
信号处理方式是:1,系统首先调用用户在进程中注册的函数,2,然后调用系统的默认
响应方式,此处我们可以注册自己的信号处理函数,在连接断开时执行
*/
#define PORT 11910
#define Buflen 1024
void process_conn_client(int s);
void sig_pipe(int signo); //用户注册的信号函数,接收的是信号值
int s; //全局变量 , 存储套接字描述符
int main(int argc,char *argv[])
{
sockaddr_in server_addr;
int err;
sighandler_t ret;
char server_ip[50] = "";
/********************socket()*********************/
s= socket(AF_INET,SOCK_STREAM,0);
if(s<0)
{
printf("client : create socket error\n");
return 1;
}
//信号处理函数 SIGINT 是当用户按一个 Ctrl-C 建时发送的信号
ret = signal(SIGTSTP,sig_pipe);
if(SIG_ERR == ret)
{
printf("信号挂接失败\n");
return -1;
}
else
printf("信号挂接成功\n") ;
/*******************connect()*********************/
//设置服务器地址结构,准备连接到服务器
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
/*将用户数入对额字符串类型的IP格式转化为整型数据*/
//inet_pton(AF_INET,argv[1],&server_addr.sin_addr.s_addr);
printf("please input server ip address : \n");
read(0,server_ip,50);
//err = inet_pton(AF_INET,server_ip,&server_addr.sin_addr.s_addr);
server_addr.sin_addr.s_addr = inet_addr(server_ip);
err = connect(s,(struct sockaddr *)&server_addr,sizeof(sockaddr));
if(err == 0)
{
printf("client : connect to server\n");
}
else
{
printf("client : connect error\n");
return -1;
}
//与服务器端进行通信
process_conn_client(s);
close(s);
}
void process_conn_client(int s)
{
ssize_t size = 0;
char buffer[Buflen];
for(;;)
{
memset(buffer,'\0',Buflen);
/*从标准输入中读取数据放到缓冲区buffer中*/
size = read(0,buffer,Buflen); // 0,被默认的分配到标准输入 1,标准输出 2,error
if(size > 0)
{
//当向服务器发送 “quit” 命令时,服务器首先断开连接
write(s,buffer,strlen(buffer)+1); //向服务器端写
//等待读取到数据
for(size = 0 ; size == 0 ; size = read(s,buffer,Buflen) );
write(1,buffer,strlen(buffer)+1); //向标准输出写
}
}
}
void sig_pipe(int signo) //传入套接字描述符
{
printf("Catch a signal\n");
if(signo == SIGTSTP)
{
printf("接收到 SIGTSTP 信号\n");
int ret = close(s);
if(ret == 0)
printf("成功 : 关闭套接字\n");
else if(ret ==-1 )
printf("失败 : 未关闭套接字\n");
exit(1);
}
}
#include <stdio.h> #include <strings.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> //#include <linux/in.h> #include <stdlib.h> #include <memory.h> #include <arpa/inet.h> #include <netinet/in.h> #include <signal.h> //添加信号处理 防止向已断开的连接通信 /** 信号处理顺序说明:在Linux操作系统中某些状况发生时,系统会向相关进程发送信号, 信号处理方式是:1,系统首先调用用户在进程中注册的函数,2,然后调用系统的默认 响应方式,此处我们可以注册自己的信号处理函数,在连接断开时执行 */ #define PORT 11910 #define Buflen 1024 void process_conn_client(int s); void sig_pipe(int signo); //用户注册的信号函数,接收的是信号值 int s; //全局变量 , 存储套接字描述符 int main(int argc,char *argv[]) { sockaddr_in server_addr; int err; sighandler_t ret; char server_ip[50] = ""; /********************socket()*********************/ s= socket(AF_INET,SOCK_STREAM,0); if(s<0) { printf("client : create socket error\n"); return 1; } //信号处理函数 SIGINT 是当用户按一个 Ctrl-C 建时发送的信号 ret = signal(SIGTSTP,sig_pipe); if(SIG_ERR == ret) { printf("信号挂接失败\n"); return -1; } else printf("信号挂接成功\n") ; /*******************connect()*********************/ //设置服务器地址结构,准备连接到服务器 memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*将用户数入对额字符串类型的IP格式转化为整型数据*/ //inet_pton(AF_INET,argv[1],&server_addr.sin_addr.s_addr); printf("please input server ip address : \n"); read(0,server_ip,50); //err = inet_pton(AF_INET,server_ip,&server_addr.sin_addr.s_addr); server_addr.sin_addr.s_addr = inet_addr(server_ip); err = connect(s,(struct sockaddr *)&server_addr,sizeof(sockaddr)); if(err == 0) { printf("client : connect to server\n"); } else { printf("client : connect error\n"); return -1; } //与服务器端进行通信 process_conn_client(s); close(s); } void process_conn_client(int s) { ssize_t size = 0; char buffer[Buflen]; for(;;) { memset(buffer,'\0',Buflen); /*从标准输入中读取数据放到缓冲区buffer中*/ size = read(0,buffer,Buflen); // 0,被默认的分配到标准输入 1,标准输出 2,error if(size > 0) { //当向服务器发送 “quit” 命令时,服务器首先断开连接 write(s,buffer,strlen(buffer)+1); //向服务器端写 //等待读取到数据 for(size = 0 ; size == 0 ; size = read(s,buffer,Buflen) ); write(1,buffer,strlen(buffer)+1); //向标准输出写 } } } void sig_pipe(int signo) //传入套接字描述符 { printf("Catch a signal\n"); if(signo == SIGTSTP) { printf("接收到 SIGTSTP 信号\n"); int ret = close(s); if(ret == 0) printf("成功 : 关闭套接字\n"); else if(ret ==-1 ) printf("失败 : 未关闭套接字\n"); exit(1); } }
运行结果
TCPServer端
TCPClient端
netstat查看网络连接
相关文章推荐
- Linux下TCP Socket编程C语言小实例
- Linux下TCP Socket编程C语言小实例
- linux下TCP Socket编程C语言小实例
- Linux C Socket TCP编程介绍及实例
- linux socket编程 TCP和UDP实例
- linux下TCP/socket编程实例
- Linux C Socket TCP编程介绍及实例
- Linux C Socket编程原理及tcp, udp简单实例
- Linux C Socket TCP编程介绍及实例
- Linux Socket编程:基于TCP/IP的客户端与服务端通讯实例
- Linux Socket 编程实例——TCP
- linux下socket编程-TCP
- (转) linux socket 编程(C语言)
- linux socket编程实例
- Linux下基于C/C++的Socket编程实例
- linux tcp Linux的SOCKET编程详解
- Linux下TCP和UDP编程实例
- Linux下Socket编程之TCP原理
- Windows下C语言的Socket编程例子(TCP和UDP)
- Linux下基本TCP socket编程之服务器端