Linux 网络编程实例

  1 /*socket->bind->listen->accept->recv/recvfrom->send/sendto->close
  2 
  3   客户端:socket->connect->send/sendto->recv/recvfrom->close
  4 
  5   其中服务器端首先建立起socket,然后调用本地端口的绑定,接着就开始与客服端建立联系,并接收客户端发送的消息。
  6   客户端则在建立socket之后调用connect函数来建立连接。
  7 
  8   服务器端的源代码如下所示:*/
  9 
 10 /*"server.c"*/
 11 
 12 #include<sys/types.h>
 13 #include<sys/socket.h>
 14 #include<stdio.h>
 15 #include<stdlib.h>
 16 #include<errno.h>
 17 #include<string.h>
 18 #include<unistd.h>
 19 #include<netinet/in.h>
 20 
 21 #define PORT  3490    //端口
 22 
 23 #define BUFFER_SIZE  1024        //缓冲区大小
 24 
 25 #define MAX_QUE_CONN_NM  5    //服务器等待连接队列的最大长度。
 26 
 27 int main(){
 28 
 29     struct sockaddr_in server_sockaddr,client_sockaddr;     //分别定义服务器和客户端套接字
 30     int sin_size,recvbytes;
 31     int server_fd,client_fd;
 32     char buf[BUFFER_SIZE];            //缓冲区
 33 
 34     /*
 35        SOCKET PASCAL FAR socket( int af, int type, int protocol);
 36        af:一个地址描述。目前仅支持AF_INET格式,也就是说ARPA Internet地址格式。
 37        type:指定socket类型。新套接口的类型描述类型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。
 38        常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。
 39        protocol:顾名思义,就是指定协议。套接口所用的协议。如调用者不想指定,可用0。
 40        常用的协议有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,
 41        它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。
 42      */
 43     if((server_fd = socket(AF_INET,SOCK_STREAM,0))== -1){  //建立socket连接www.linuxidc.com
 44         perror("create socket fail");
 45         exit(1);
 46     }
 47 
 48     printf("Socket id=%d\n",server_fd);
 49 
 50     /*设置sockaddr_in结构体中的相关参数*/
 51 
 52     server_sockaddr.sin_family = AF_INET;
 53     server_sockaddr.sin_port = htons(PORT);   //由于在写网络程序时字节的网络顺序和主机顺序会有问题
 54     server_sockaddr.sin_addr.s_addr = INADDR_ANY;    //即0.0.0.0 任意地址
 55     bzero(&(server_sockaddr.sin_zero),8);
 56     int i = 1;  //允许重复使用本地地址与套接字进行绑定
 57 
 58     /*int PASCAL FAR setsockopt(SOCKET s,int level,int optname,const char FAR *optval,int optlen);
 59       s:标识一个套接字的描述符。
 60       level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。
 61       optname:需设置的选项。
 62       optval:指针,指向存放选项值的缓冲区。
 63       optlen:optval缓冲区长度。
 64      */
 65     setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i));  
 66 
 67     /*
 68        int bind(SOCKET socket, const struct sockaddr *address,
 69        socklen_t address_len);
 70        参数说明:
 71        socket:是一个套接字。
 72        address:是一个sockaddr结构指针,该结构中包含了要结合的地址和端口号。
 73        address_len:确定address缓冲区的长度。
 74        返回值:如果函数执行成功,返回值为0,否则为SOCKET_ERROR。
 75      */
 76     if(bind(server_fd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr)) == -1){  //绑定函数bind
 77         perror("bind fail");
 78         exit(1);
 79     }
 80 
 81     printf("Bind success!\n");
 82 
 83     /*
 84        int PASCAL FAR listen( SOCKET s, int backlog);
 85        S:用于标识一个已捆绑未连接套接口的描述字。
 86        backlog:等待连接队列的最大长度。
 87      */
 88     if(listen(server_fd,MAX_QUE_CONN_NM)== -1){  //调用listen函数,创建为处理请求的队列
 89         perror("listen fail");
 90         exit(1);
 91     }
 92 
 93     printf("Listening......\n");
 94 
 95     /*
 96        SOCKET PASCAL FAR accept( SOCKET s, struct sockaddr FAR* addr,int FAR* addrlen);
 97        s:套接口描述字,该套接口在listen()后监听连接。
 98        addr:(可选)指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。
 99        addrlen:(可选)指针,输入参数,配合addr一起使用,指向存有addr地址长度的整型数。
100      */
101     if((client_fd = accept(server_fd,(struct sockaddr *)&client_sockaddr,&sin_size))==-1){//调用accept函数,等待客户端的接
102         perror("accept fail");
103         exit(1);
104     }
105 
106     printf("server: got connection from %s \n",inet_ntoa(client_sockaddr.sin_addr));
107 
108     memset(buf,0,sizeof(buf));
109     /*
110        int PASCAL FAR recv( SOCKET s, char FAR* buf, int len, int flags);
111        s:一个标识已连接套接口的描述字。
112        buf:用于接收数据的缓冲区。
113        len:缓冲区长度。
114        flags:指定调用方式。通常写成0
115      */
116     if((recvbytes = recv(client_fd,buf,BUFFER_SIZE,0)) == -1){//调用recv函数接收客户端的请求
117         perror("recv fail");
118         exit(1);
119     }
120     
121     printf("Received a message: %s\n",buf);
122     
123 
124     /*向客户起写数据*/        
125     if(write(client_fd,"客户端我收到你发来的数据了,你能收到这句应答吗?\n",1024)==-1)
126         perror("write error!");        
127     
128     close(client_fd);
129 
130     close(server_fd);
131     exit(0);
132 }
133 
134 
135 
136 
137 
138 /*客户端*/
139 /*client.c  运行方式:./client localhost*/
140 #include <stdio.h>
141 #include <stdlib.h>
142 #include <errno.h>
143 #include <string.h>
144 #include <netdb.h>
145 #include <sys/types.h>
146 #include <netinet/in.h>
147 #include <sys/socket.h>
148 #define PORT 3490
149 #define MAXDATASIZE 5000
150 int main(int argc,char **argv)
151 {
152     int sockfd,nbytes;
153     char buf[1024];
154     struct hostent *he;
155     struct sockaddr_in srvaddr;
156     if(argc!=2)
157     {
158         perror("Usage:client hostname\n");
159         exit(1);
160     }
161     /*函数gethostbyname获得指定域名地址所对应的ip地址*/
162     if((he=gethostbyname(argv[1]))==NULL)
163     {
164         perror("gethostbyname");
165         exit(1);
166     }
167     /*创建套接字,返回套接字描述符*/
168     if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
169     {
170         perror("create socket error");
171         exit(1);
172     }
173     bzero(&srvaddr,sizeof(srvaddr));
174     /*用获得的远程服务器进程的ip地址和端口号来填充一个internet套接字地址结构*/
175     srvaddr.sin_family=AF_INET;
176     srvaddr.sin_port=htons(PORT);
177     srvaddr.sin_addr=*((struct in_addr *)he->h_addr);
178     /*用connect于这个远程服务器建立一个internet连接*/
179     if(connect(sockfd,(struct sockaddr *)&srvaddr,sizeof(struct sockaddr))==-1)
180     {
181         perror("connect error");
182         exit(1);
183     }
184     
185     
186     if((send(sockfd,"客户端向服务端发送数据,服务端你收到了吗?",1024,0)) == -1)
187     {
188         perror("send error");
189         exit(1);
190     }
191     
192 
193     
194     /*调用read函数读取服务器write过来的信息*/
195     if((nbytes=read(sockfd,buf,MAXDATASIZE))==-1)
196     {
197         perror("read error");
198         exit(1);
199     }
200     buf[nbytes]='\0';
201     printf("read: %s",buf);
202     close(sockfd);
203 }
View Code

 

运行方式: gcc -o service service.c

      gcc -o client client.c

     chmod +x service

      chmod +x client

在一个终端运行:./service

在另一个终端运行:./client localhost

服务端输出:

Socket id=3 Bind success! Listening...... server: got connection from 127.0.0.1 Received a message: 客户端向服务端发送数据,服务端你收到了吗?

 

客户端输出:

read: 客户端我收到你发来的数据了,你能收到这句应答吗?

posted @ 2013-10-31 17:22  奔跑的小蜗牛  阅读(724)  评论(0编辑  收藏  举报