赞
踩
1.预备知识介绍
以下函数发生错误均可查看errno错误原因
int socket(int domain, int type,int protocol)
举例:socket(AF_INET,SOCK_STREAM,0);
头文件:
#include<sys/systypes.h>
#include<sys/socket.h>
第一个参数是指协议族类型,第二个参数表示套接字通信的类型,第三个表示一个协议的不同种类选择,只有一种就是0.
返回值失败返回-1,成功返回这个socket对应的文件描述符。
int bind(int sockfd,const struct sockaddr *my_addr,socklen_t addrlen)
第一个参数是对应socket的文件描述符
第二个参数是指向sockaddr结构的指针,这个结构包含地址,端口和ip信息
第三个参数是长度,一般用sizeof(struct sockaddr)即可
int listen(int sockfd,int backlog)
第一个参数是socket对应文件描述符,第二个参数是accept函数处理之前等待队列中客户端的个数,超过这个个数客户端就会返回一个ECONNREFUSED错误
当listen成功运行时,返回值是0,运行失败返回-1;有些协议可能不支持listen,如SOCK_DGRAM
接受一个网络请求accept
int accept(int sockfd,struct sockaddr *addr, socklen_t *addrlen);
该函数返回值是客户端socket的文件描述符
通过该函数可以获得客户端的IP地址,端口和协议等等,存在addr指针中。
int connect(int sockfd,struct sockaddr* ,int addrlen)
该函数成功返回0,发生错误返回-1.
第一个参数为建立客户端套接字返回的文件描述符
第二个参数为指针,包括客户端需要连接服务器的目的端口和IP地址,以及协议类型。第三个参数设为sizeof(struct sockaddr)即可
2.测试程序
服务器端(tcpserver.c)
- #include<stdio.h>
- #include<stdlib.h>
- #include<strings.h>
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<unistd.h>
- #include<arpa/inet.h>
-
-
- #define port 8888
- #define queuelong 2 //监听队列长度
-
- void process_conn_server(int s) //处理客户端传过来的消息,参数为客户端socket的描述符
- {
- ssize_t size=0;
- char buffer[1024];
- for(;;)
- {
- size=read(s,buffer,1024); //从客户端socket读数据
- if(size==0)return ;
-
- //构建响应字符,为接收到客户端字节数量
- sprintf(buffer,"%d bytes altogether\n",size); //写在buffer里
- write(s,buffer,strlen(buffer)+1); //发送给客户端
-
- }
-
- }
-
- int main(int argc,int *argv[])
- {
- int ss,sc; //ss为服务器socket描述符,sc为客户端socket描述符
- struct sockaddr_in server_addr; //服务器地址结构
- struct sockaddr_in client_addr; //客户端地址结构
- int err; //返回值
- pid_t pid; //分支进程号
-
- //建立套接字
- ss=socket(AF_INET,SOCK_STREAM,0);
- if(ss<0)
- {
- printf("socket error!!!");
- return -1;
-
- }
- //设置服务器地址
-
- bzero(&server_addr,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(server_addr));
- if(err<0)
- {
- printf("listen error!");
- return -1;
-
- }
- err=listen(ss,queuelong); //监听
- if(err<0)
- {
- printf("listen failed!");
- return -1;
- }
-
- printf("bind is over!");
- //主循环
-
- for(;;)
- {
- socklen_t addrlen=sizeof(struct sockaddr);
- sc=accept(ss,(struct sockaddr*)&client_addr,&addrlen); //接受客户端请求
- if(sc<0)
- continue;
-
- pid=fork(); //为每一个客户请求复制一个子进程
- printf("sub process is create!");
- if(pid==0)
- {
- close(ss);
- process_conn_server(sc); //子进程处理
- }
- else
- close(sc);
-
-
- }

客户端(tcpclient.c)
- #include<stdio.h>
- #include<unistd.h>
- #include<string.h>
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<arpa/inet.h>
- #define PORT 8888
- void process_conn_client(int s)
- {
- ssize_t size=0;
- char buffer[1024];
- for(;;)
- {
- size=read(0,buffer,1024); //从标准输入读入数据
- if(size>0)
- {
- write(s,buffer,size); //给服务器写数据
- size=read(s,buffer,1024); //读数据
- write(1,buffer,size);//向屏幕写
-
- }
- }
-
- }
-
- int main(int argc,char *argv[])
- {
- int s; //socket描述符
- struct sockaddr_in server_addr;
-
- s=socket(AF_INET,SOCK_STREAM,0); //建立客户端socket
- if(s<0)
- {
- printf("socket error!!");
- return -1;
- }
- //设置连接的服务器地址
- bzero(&server_addr,sizeof(server_addr)); //清零
- server_addr.sin_family=AF_INET; //协议类型
- server_addr.sin_addr.s_addr=htonl(INADDR_ANY); //ip--这里是任意地网卡地址
- server_addr.sin_port=htons(PORT); //端口
-
-
- //将用户输入的字符串类型的ip地址转换成整形
-
- inet_pton(AF_INET,argv[1],&server_addr.sin_addr);
- printf("begin to connect!");
-
- //连接服务器
- connect(s,(struct sockaddr*)&server_addr,sizeof(struct sockaddr));
- process_conn_client(s);
- printf("process_conn_client is over!");
- close(s);
- return 0;
-
- }

3.测试及结果
分别编译两个.c文件,得到两个可执行文件
先开一个终端,执行tcpserver
再开一个执行:
以上就是效果!
最后总结一下linux下tcp的步骤
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。