简单socket通信的服务器端程序如下:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#define SERVER_PORT 3456
#define DEBUG 0 //debug macro
#define TRUE 1
#define FALSE 0
int
main(int argc,char **argv){
int listen_sfd,max_sfd,new_sfd;
int on=1,rv,ready_sfd_num,i,connection_close=FALSE,server_end=FALSE;
fd_set master_set,working_set;
struct sockaddr_in sockaddr;
struct timeval timeout;
char buf[100];
/*
* create a AF_INET SOCKET_STREAM socket
* */
listen_sfd=socket(AF_INET,SOCK_STREAM,0);
if(listen_sfd < 0){
perror("server socket ");
exit(EXIT_FAILURE);
}
#if DEBUG
printf("listen_sfd=%d\n",listen_sfd);
#endif
/*
* set socket to SO_REUSEADDR
* */
rv=setsockopt(listen_sfd,SOL_SOCKET,SO_REUSEADDR,(void *)&on,sizeof(on));
if(rv < 0){
perror("server setsockopt");
close(listen_sfd);
exit(EXIT_FAILURE);
}
/*
* set socket to non-blocking
* */
rv=fcntl(listen_sfd,F_SETFL,O_NONBLOCK);
if(rv<0){
perror("server fcntl ");
close(listen_sfd);
exit(EXIT_FAILURE);
}
/*
* bind socket to localhost interface
* */
memset(&sockaddr,0,sizeof(sockaddr));
sockaddr.sin_family =AF_INET;
sockaddr.sin_port =htons(SERVER_PORT);
sockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
rv=bind(listen_sfd,(struct sockaddr *)&sockaddr,sizeof(sockaddr));
if(rv<0){
perror("server bind ");
close(listen_sfd);
exit(EXIT_FAILURE);
}
/*
* set back log to 10
* */
rv=listen(listen_sfd,10);
if(rv<0){
perror("server listen ");
close(listen_sfd);
exit(EXIT_FAILURE);
}
/*
* file descriptors set operations
* */
FD_ZERO(&master_set);
FD_ZERO(&working_set);
max_sfd=listen_sfd;
FD_SET(listen_sfd,&master_set);
/*
* infinite loop of select
* */
while(1){
memcpy(&working_set,&master_set,sizeof(master_set));
/*
* set timeout value to 2 minutes
* */
timeout.tv_sec =2*60;
timeout.tv_usec=0;
ready_sfd_num=select(max_sfd+1,&working_set,NULL,NULL,&timeout);
/*
* select return value has three conditions:
* 1.<0 ---error
* 2.==0---timeout value expires
* 3.>0 ---successful
* */
if(ready_sfd_num<0){
perror("server select ");
break;
}
if(ready_sfd_num==0){
printf("Time Out,End Program!\n");
break;
}
/*
* when select function is invoked successfully,there exists two conditions:
* 1.new connections
* 2.new data
* */
for(i=0;i<=max_sfd && ready_sfd_num>0;++i){
if(FD_ISSET(i,&working_set)){
ready_sfd_num--;
/*
* new connection coming ,accept all incoming connections in queue list
* */
if(i==listen_sfd){
while(1){
new_sfd=accept(listen_sfd,NULL,NULL);
if(new_sfd <0){
if(errno != EWOULDBLOCK){
perror("server accept");
server_end=TRUE;
}
break;
}
if(new_sfd >0){
/*
* set new_sfd to non-blocking
* */
rv=fcntl(new_sfd,F_SETFL,O_NONBLOCK);
if(rv<0){
perror("server fcntl ");
close(new_sfd);
break;
}
FD_SET(new_sfd,&master_set);
if(new_sfd>max_sfd)
max_sfd=new_sfd;
printf("new connection created,socket---%d\n",new_sfd);
}
}
}
/*
* new data coming on connected socket
* */
else{
while(1){
rv=recv(i,buf,sizeof(buf),0);
if(rv<0){
if(errno != EWOULDBLOCK ){
perror("servre recv");
connection_close=TRUE;
}
break;
}
if(rv==0){
connection_close=TRUE;
break;
}
printf("server receive:%s,from socket---%d\n",buf,i);
}
}
if(connection_close){
close(i);
printf("%d socket closed!\n",i);
FD_CLR(i,&master_set);
if(i==max_sfd){
while(FD_ISSET(max_sfd,&master_set)==FALSE)
max_sfd--;
}
}
}
}//end of ready sfd loop
/*determine whether end server or not*/
if(server_end)
break;
}//end of select
/*
* cleanup
* */
while(max_sfd>=0){
if(FD_ISSET(max_sfd,&master_set))//which one :working_set or master_set!!!!master_set
close(max_sfd);
max_sfd--;
}
return 0;
}//end of main
客户端程序如下:
/*
** client.c -- a stream socket client demo
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define PORT "9034" // the port client will be connecting to
#define MAXDATASIZE 100 // max number of bytes we can get at once
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(int argc, char *argv[])
{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
if (argc != 2) {
fprintf(stderr,"usage: client hostname\n");
exit(1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("client: connect");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "client: failed to connect\n");
return 2;
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("client: received '%s'\n",buf);
close(sockfd);
return 0;
}