Linux socket网络编程基础 tcp协议和udp协议,socketudp
Linux socket网络编程基础 tcp协议和udp协议,socketudp
Socket TCP网络通信编程
首先,服务器端需要做以下准备工作:
(1)调用socket()函数。建立socket对象,指定通信协议。
(2)调用bind()函数。将创建的socket对象与当前主机的某一个IP地和端口绑定。
(3)调用listen()函数。使socket对象处于监听状态,并设置监听队列大小。
客户端需要做以下准备工作:
(1)调用socket()函数。建立socket()对象,指定相同通信协议。
(2)应用程序可以显式的调用bind()函数为其绑定IP地址和端口,当然,也可以将这工作交给TCP/IP协议栈。
接着建立通信连接:
(1)客户端调用connect()函数。向服务器端发出连接请求。
(2)服务端监听到该请求,调用accept()函数接受请求,从而建立连接,并返回一个新的socket文件描述符专门处理该连接。
然后通信双方发送/接收数据:
(1)服务器端调用write()或send()函数发送数据,客户端调用read()或者recv()函数接收数据。反之客户端发送数据,服务器端接收数据。
(2)通信完成后,通信双方都需要调用close()或者shutdown()函数关闭socket对象。
类比电话通信,面向连接的socket通信实现图
展示一个代码示例:
服务端:
#include<stdio.h> #include<sys/socket.h> #include<netinet/in.h> #include<string.h> #include<unistd.h> #include <arpa/inet.h> #include<pthread.h> static void usage(const char *proc) { printf("Please use :%s [IP] [port]\n",proc); } void thread_run(void *arg) { printf("creat a new thread\n"); int fd = (int)arg; char buf[1024]; while(1){ memset(buf,'\0',sizeof(buf)); ssize_t _s = read(fd,buf,sizeof(buf) - 1); if(_s > 0){ buf[_s] = '\0'; printf("client say : %s\n",buf); } memset(buf,'\0',sizeof(buf)); printf("please Enter: "); fflush(stdout); ssize_t _s2 = read(0,buf,sizeof(buf) - 1); if(_s2 > 0){ write(fd,buf,strlen(buf)); } } } int main(int argc,char *argv[]) { if(argc != 3){ usage(argv[0]); exit(1); } //1.creat socket int sock = socket(AF_INET,SOCK_STREAM,0); if(sock < 0){ perror("creat socket error\n"); return 1; } struct sockaddr_in local; local.sin_family = AF_INET; local.sin_port = htons(atoi(argv[2])); local.sin_addr.s_addr = inet_addr(argv[1]); //2.bind if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){ perror("bind error\n"); close(sock); return 2; } //3.listen if(listen(sock,10) < 0){ perror("listen error\n"); close(sock); return 3; } printf("bind and listen success!wait accept...\n"); //4.accept struct sockaddr_in peer; socklen_t len = sizeof(peer); while(1){ int fd = accept(sock,(struct sockaddr*)&peer ,&len); if(fd < 0){ perror("accept error\n"); close(sock); return 4; } printf("get connect,ip is : %s port is : %d\n",inet_ntoa(peer.sin_addr),ntohs(peer.sin_port)); pthread_t id; pthread_create(&id,NULL,thread_run,(void*)fd); pthread_detach(id); } close(sock); return 0; }
客户端:
#include<stdio.h> #include<unistd.h> #include<sys/socket.h> #include<sys/types.h> #include<string.h> #include<errno.h> #include<netinet/in.h> #include<arpa/inet.h> static void usage(const char *proc) { printf("please use : %s [ip] [port]\n",proc); } int main(int argc,char *argv[]) { if( argc != 3 ){ usage(argv[0]); exit(1); } int sock = socket(AF_INET,SOCK_STREAM,0); if(sock < 0){ perror("socket error"); return 1; } struct sockaddr_in remote; remote.sin_family = AF_INET; remote.sin_port = htons(atoi(argv[2])); remote.sin_addr.s_addr = inet_addr(argv[1]); int ret = connect(sock,(struct sockaddr*)&remote,sizeof(remote)); if(ret < 0){ printf("connect failed:%s\n",strerror(errno)); return 2; } printf("connect success!\n"); char buf[1024]; while(1){ memset(buf,'\0',sizeof(buf)); printf("please enter:"); fflush(stdout); ssize_t _s = read(0,buf,sizeof(buf)-1); if(_s > 0){ buf[_s - 1] = '\0'; write(sock,buf,strlen(buf)); _s = read(sock,buf,sizeof(buf)-1); if(_s > 0){ if(strncasecmp(buf,"quit",4) == 0){ printf("qiut\n"); break; } buf[_s -1] = '\0'; printf("%s\n",buf); } } } close(sock); return 0; }
UDP网络通信编程
客户不与服务器建立链接,而是管使用sendto函数给服务器发送数据报,其中必须指定目的地址(即服务器地址)作为参数。类似的,服务器不接受来自客户的连接,而只管调用
revcfrom函数等待来自某个客户数据的到达。revcfrom将与所接受到的数据报一道返回客户的协议地址,因此服务器可以把响应发送给正确的客户。
int sendto (int s, const void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen);
int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
第一个参数为发送的目标socket对象。
第二个参数为欲发送的数据信息。
第三个参数为发送数据的大小。
第四个参数为flags,如send函数所示。
第五个参数欲发送数据的目标地址,其结构体前面已经介绍。
第六个参数为此结构体的大小。
服务端代码示例:#include<stdio.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<string.h> int main(int argc,char *argv[]) { if(argc != 3){ printf("Please Enter: %s [ip] [port]",argv[0]); return 1; } int sock = socket(AF_INET,SOCK_DGRAM,0); if(sock < 0){ perror("socket error"); return 2; } struct sockaddr_in remote; remote.sin_family = AF_INET; remote.sin_port = htons(atoi(argv[2])); remote.sin_addr.s_addr = inet_addr(argv[1]); if(bind(sock,(struct sockaddr*)&remote,sizeof(remote)) < 0){ perror("bind error"); return 3; } int done = 0; struct sockaddr_in peer; socklen_t len = sizeof(peer); char buf[1024]; while(!done){ memset(buf,'\0',sizeof(buf)); printf("Please Enter:"); fflush(stdout); ssize_t _s = read(0,buf,sizeof(buf)-1 ); if(_s > 0){ buf[_s -1] = '\0'; sendto(sock,buf,sizeof(buf),0,(struct sockaddr*)&remote,sizeof(remote)); memset(buf,'\0',sizeof(buf)); recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr*)&peer,&len); printf("server echo %s,socket :&s:&d\n",buf,inet_ntoa(peer.sin_addr),ntohs(peer.sin_port)); } } return 0; }客户端代码示例:
评论暂时关闭