买了一本书:完全手册Linux系统下C程序开发详解 里面的网络tcp那块的节选,感觉不错,贴出来一下:
所谓服务器程序,指的是在网络通信时这个程序始终处于等待状态,可以接受用户的连接请求,并且对用户发送的信息进行处理,本节的实例是面向连接的套接字通信服务器程序。程序的重点是端口的监听和接收发送的信息。
代码17-7 TCP服务器程序:\源文件\17\17.25.c
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h> /*包含头文件。*/
#define PORT 5678 /*定义端口号。*/
#define MAX 10 /*最多的连接数。*/
main()
{
int sockfd,newsockfd,is_connected[MAX],fd; /*定义相关的变量。*/
struct sockaddr_in addr;
int addr_len = sizeof(struct sockaddr_in);
fd_set myreadfds;
char msgbuffer[256];
char msg[] ="This is the message from server.Connected.\n";
if ((sockfd = socket(AF_INET,SOCK_STREAM,0))<0) /*建立一个socket。*/
{
perror("socket");
exit(1);
}
else
{
printf("socket created .\n"); /*socket建立成功,输出提示。*/
printf("socked id: %d \n",sockfd);
}
bzero(&addr,sizeof(addr)); /*清空addr所在的内存。*/
addr.sin_family =AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sockfd,&addr,sizeof(addr))<0) /*绑定端口。*/
{
perror("connect");
exit(1);
}
else
{
printf("connected.\n");
printf("local port:%d\n",PORT) ;
}
if(listen(sockfd,3)<0) /*开始监听。*/
{
perror("listen");
exit(1);
}
else
{
printf("listenning......\n");
}
for(fd=0;fd<MAX;fd++)
{
is_connected[fd]=0; /*设置所有的标记为0。*/
}
while(1) /*进入一个循环,处理所有的连接。*/
{
FD_ZERO(&myreadfds); /*清空一个标志。*/
FD_SET(sockfd,&myreadfds); /*设置标志。*/
for(fd=0;fd<MAX;fd++)
{
if(is_connected[fd]) /*判断有没有连接。*/
{
FD_SET(fd,&myreadfds); /*设置标志。*/
}
}
if(!select(MAX,&myreadfds,NULL,NULL,NULL)) /*如果到达了最大的连接数则进
入下次循环。*/
{
continue;
}
for(fd=0;fd<MAX;fd++) /*进入一个循环。*/
{
if(FD_ISSET(fd,&myreadfds)) /*判断标志。*/
{
if(sockfd==fd) /*如果新建的socket与fd相同。*/
{
if((newsockfd = accept (sockfd,&addr,&addr_len))<0)
/*接受一个连接,新建一个socket。*/
{
perror("accept");
}
write(newsockfd,msg,sizeof(msg)); /*给客户端发送一段信息。*/
is_connected[newsockfd] =1; /*设置标志。*/
printf("cnnect from %s\n",inet_ntoa(addr.sin_addr));
/*输出客户端的IP。*/
}
else
{
bzero(msgbuffer,sizeof(msgbuffer)); /*清空字符串。*/
if(read(fd,msgbuffer,sizeof(msgbuffer))<=0)
/*读取结果。*/
{
printf("connect closed.\n"); /*输出连接关闭。*/
is_connected[fd]=0; /*设置标志。*/
close(fd); /*关闭一个socket。*/
}
else
{
write(fd,msgbuffer,sizeof(msgbuffer));
/*发送接收到的信息。*/
printf("message:%s \n",msgbuffer);
/*输出接收到的信息。*/
}
}
}
}
}
}
输入下面的命令,编译这个程序。需要加-o参数指定一个输出文件名。
gcc 17.25.c -o tcpser
输入下面的命令,对这个程序添加可执行权限。
chmod +x udpcli
客户端指的是在网络通信时主动向服务器发送连接请求,主动发送信息的程序。本节将讲述面向连接的套接字通信的客户端程序。这个程序的主要内容是向服务器申请连接,并且发送用户输入的内容。
代码17-8 TCP客户端程序:\源文件\17\17.26.c
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h> /*包含头文件。*/
#define PORT 5678 /*定义远程端口。*/
#define REMOTE_IP "127.0.0.1" /*定义远程IP。*/
int main(int argc,char *argv[])
{
int s ; /*定义相关变量。*/
struct sockaddr_in addr ;
char mybuffer[256];
if( (s=socket(AF_INET,SOCK_STREAM,0))<0 ) /*新建一个socket。*/
{
perror("socket");
exit(1);
}
else
{
printf("socket created .\n");
printf("socked id: %d \n",s);
}
bzero(&addr,sizeof(addr)); /*设置addr。*/
addr.sin_family =AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr=inet_addr(REMOTE_IP);
if(connect(s,&addr,sizeof(addr))<0) /*连接远程服务器。*/
{
perror("connect");
exit(1);
}
else
{
printf("connected ok!\n");
printf("remote ip:%s\n",REMOTE_IP);
printf("remote port:%d\n",PORT);
}
recv(s ,mybuffer,sizeof(mybuffer),0); /*接收服务器发送的信息。*/
printf("%s\n",mybuffer); /*输出信息。*/
while(1) /*进入一个循环。*/
{
bzero(mybuffer,sizeof(mybuffer)); /*清空mybuffer字符串。*/
read(STDIN_FILENO,mybuffer,sizeof(mybuffer)); /*读取输入。*/
if(send(s,mybuffer,sizeof(mybuffer),0)<0) /*发送信息。*/
{
perror("send"); /*错误处理。*/
exit(1);
}
else
{
bzero(mybuffer,sizeof(mybuffer)); /*清空mybuffer内存。*/
recv(s ,mybuffer,sizeof(mybuffer),0); /*接收信息。*/
printf("received:%s\n",mybuffer); /*输出信息。*/
}
}
}
输入下面的命令,编译这个程序。需要加-o参数指定一个输出文件名。
gcc 17.26.c -o tcpcli
输入下面的命令,对这个程序添加可执行权限。
chmod +x udpcli
本节将对面向连接套接字通信的两个实例程序进行测试。在运行这两个程序时,需要先打开服务程序,使相应的端口处于监听状态,然后打开客户端程序,请求连接服务器的端口。
(1)输入下面的命令,运行服务器程序。
./tcpser
(2)程序的运行结果如下所示。
socket created .
socked id: 3
connected.
local port:5678
listenning......
(3)结果显示,已经建立socket,本地端口是5678。程序正在这个端口上进行监听。
(4)这时打开另一个终端,在终端中输入下面的命令,打开客户端程序。
./tcpcli
(5)程序显示的结果如下所示。结果显示程序已经建立了socket连接到了127.0.0.1这个IP上的5678号端口。服务器发送回一条信息。
socket created .
socked id: 3
connected ok!
remote ip:127.0.0.1
remote port:5678
This is the message from server.Connected.
(6)在服务器程序的终端中查看,显示的结果如下所示。
cnnect from 127.0.0.1
(7)结果表示服务器已经接受了客户端的连接请求。
(8)这时进入客户程序的终端,输入“hello”,然后按“Enter”键。显示的结果如下所示。
received:hello
(9)结果表明,程序把输入的字符串发送到了服务器,服务器又返回了这个字符串。
(10)进入到服务器的终端,可以查看到客户端发送的信息如下所示。
message:hello
(11)这两个程序进入了while循环以后,会始终执行程序无法退出。可以按“Ctrl”+“C”组合键结束程序。
所谓服务器程序,指的是在网络通信时这个程序始终处于等待状态,可以接受用户的连接请求,并且对用户发送的信息进行处理,本节的实例是面向连接的套接字通信服务器程序。程序的重点是端口的监听和接收发送的信息。
代码17-7 TCP服务器程序:\源文件\17\17.25.c
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h> /*包含头文件。*/
#define PORT 5678 /*定义端口号。*/
#define MAX 10 /*最多的连接数。*/
main()
{
int sockfd,newsockfd,is_connected[MAX],fd; /*定义相关的变量。*/
struct sockaddr_in addr;
int addr_len = sizeof(struct sockaddr_in);
fd_set myreadfds;
char msgbuffer[256];
char msg[] ="This is the message from server.Connected.\n";
if ((sockfd = socket(AF_INET,SOCK_STREAM,0))<0) /*建立一个socket。*/
{
perror("socket");
exit(1);
}
else
{
printf("socket created .\n"); /*socket建立成功,输出提示。*/
printf("socked id: %d \n",sockfd);
}
bzero(&addr,sizeof(addr)); /*清空addr所在的内存。*/
addr.sin_family =AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sockfd,&addr,sizeof(addr))<0) /*绑定端口。*/
{
perror("connect");
exit(1);
}
else
{
printf("connected.\n");
printf("local port:%d\n",PORT) ;
}
if(listen(sockfd,3)<0) /*开始监听。*/
{
perror("listen");
exit(1);
}
else
{
printf("listenning......\n");
}
for(fd=0;fd<MAX;fd++)
{
is_connected[fd]=0; /*设置所有的标记为0。*/
}
while(1) /*进入一个循环,处理所有的连接。*/
{
FD_ZERO(&myreadfds); /*清空一个标志。*/
FD_SET(sockfd,&myreadfds); /*设置标志。*/
for(fd=0;fd<MAX;fd++)
{
if(is_connected[fd]) /*判断有没有连接。*/
{
FD_SET(fd,&myreadfds); /*设置标志。*/
}
}
if(!select(MAX,&myreadfds,NULL,NULL,NULL)) /*如果到达了最大的连接数则进
入下次循环。*/
{
continue;
}
for(fd=0;fd<MAX;fd++) /*进入一个循环。*/
{
if(FD_ISSET(fd,&myreadfds)) /*判断标志。*/
{
if(sockfd==fd) /*如果新建的socket与fd相同。*/
{
if((newsockfd = accept (sockfd,&addr,&addr_len))<0)
/*接受一个连接,新建一个socket。*/
{
perror("accept");
}
write(newsockfd,msg,sizeof(msg)); /*给客户端发送一段信息。*/
is_connected[newsockfd] =1; /*设置标志。*/
printf("cnnect from %s\n",inet_ntoa(addr.sin_addr));
/*输出客户端的IP。*/
}
else
{
bzero(msgbuffer,sizeof(msgbuffer)); /*清空字符串。*/
if(read(fd,msgbuffer,sizeof(msgbuffer))<=0)
/*读取结果。*/
{
printf("connect closed.\n"); /*输出连接关闭。*/
is_connected[fd]=0; /*设置标志。*/
close(fd); /*关闭一个socket。*/
}
else
{
write(fd,msgbuffer,sizeof(msgbuffer));
/*发送接收到的信息。*/
printf("message:%s \n",msgbuffer);
/*输出接收到的信息。*/
}
}
}
}
}
}
输入下面的命令,编译这个程序。需要加-o参数指定一个输出文件名。
gcc 17.25.c -o tcpser
输入下面的命令,对这个程序添加可执行权限。
chmod +x udpcli
客户端指的是在网络通信时主动向服务器发送连接请求,主动发送信息的程序。本节将讲述面向连接的套接字通信的客户端程序。这个程序的主要内容是向服务器申请连接,并且发送用户输入的内容。
代码17-8 TCP客户端程序:\源文件\17\17.26.c
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h> /*包含头文件。*/
#define PORT 5678 /*定义远程端口。*/
#define REMOTE_IP "127.0.0.1" /*定义远程IP。*/
int main(int argc,char *argv[])
{
int s ; /*定义相关变量。*/
struct sockaddr_in addr ;
char mybuffer[256];
if( (s=socket(AF_INET,SOCK_STREAM,0))<0 ) /*新建一个socket。*/
{
perror("socket");
exit(1);
}
else
{
printf("socket created .\n");
printf("socked id: %d \n",s);
}
bzero(&addr,sizeof(addr)); /*设置addr。*/
addr.sin_family =AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr=inet_addr(REMOTE_IP);
if(connect(s,&addr,sizeof(addr))<0) /*连接远程服务器。*/
{
perror("connect");
exit(1);
}
else
{
printf("connected ok!\n");
printf("remote ip:%s\n",REMOTE_IP);
printf("remote port:%d\n",PORT);
}
recv(s ,mybuffer,sizeof(mybuffer),0); /*接收服务器发送的信息。*/
printf("%s\n",mybuffer); /*输出信息。*/
while(1) /*进入一个循环。*/
{
bzero(mybuffer,sizeof(mybuffer)); /*清空mybuffer字符串。*/
read(STDIN_FILENO,mybuffer,sizeof(mybuffer)); /*读取输入。*/
if(send(s,mybuffer,sizeof(mybuffer),0)<0) /*发送信息。*/
{
perror("send"); /*错误处理。*/
exit(1);
}
else
{
bzero(mybuffer,sizeof(mybuffer)); /*清空mybuffer内存。*/
recv(s ,mybuffer,sizeof(mybuffer),0); /*接收信息。*/
printf("received:%s\n",mybuffer); /*输出信息。*/
}
}
}
输入下面的命令,编译这个程序。需要加-o参数指定一个输出文件名。
gcc 17.26.c -o tcpcli
输入下面的命令,对这个程序添加可执行权限。
chmod +x udpcli
本节将对面向连接套接字通信的两个实例程序进行测试。在运行这两个程序时,需要先打开服务程序,使相应的端口处于监听状态,然后打开客户端程序,请求连接服务器的端口。
(1)输入下面的命令,运行服务器程序。
./tcpser
(2)程序的运行结果如下所示。
socket created .
socked id: 3
connected.
local port:5678
listenning......
(3)结果显示,已经建立socket,本地端口是5678。程序正在这个端口上进行监听。
(4)这时打开另一个终端,在终端中输入下面的命令,打开客户端程序。
./tcpcli
(5)程序显示的结果如下所示。结果显示程序已经建立了socket连接到了127.0.0.1这个IP上的5678号端口。服务器发送回一条信息。
socket created .
socked id: 3
connected ok!
remote ip:127.0.0.1
remote port:5678
This is the message from server.Connected.
(6)在服务器程序的终端中查看,显示的结果如下所示。
cnnect from 127.0.0.1
(7)结果表示服务器已经接受了客户端的连接请求。
(8)这时进入客户程序的终端,输入“hello”,然后按“Enter”键。显示的结果如下所示。
received:hello
(9)结果表明,程序把输入的字符串发送到了服务器,服务器又返回了这个字符串。
(10)进入到服务器的终端,可以查看到客户端发送的信息如下所示。
message:hello
(11)这两个程序进入了while循环以后,会始终执行程序无法退出。可以按“Ctrl”+“C”组合键结束程序。
作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/3365/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
评论列表