Socket TCP網路通信編程 首先,伺服器端需要做以下準備工作: (1)調用socket()函數。建立socket對象,指定通信協議。 (2)調用bind()函數。將創建的socket對象與當前主機的某一個IP地和埠綁定。 (3)調用listen()函數。使socket對象處於監聽狀態,並設置 ...
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; }客戶端代碼示例: