轉自:https://blog.csdn.net/cabing2005/article/details/53068880
詳細函數以及參數解釋請看原鏈接。
windows下的tcp/udp參考:http://www.cnblogs.com/lyggqm/p/6558002.html
TCP SERVER:
// // main.cpp // linux_socket_api // // Created by bikang on 16/11/2. // Copyright (c) 2016年 bikang. All rights reserved. // #include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> #include <assert.h> #include <stdio.h> #include <string.h> //using namespace std; #define BUFFER_SIZE 1024 void tsocket(int argc, const char * argv[]); int main(int argc, const char * argv[]) { tsocket(argc,argv); return 0; } void tsocket(int argc, const char * argv[]){ if(argc < 3){ exit(-1); } const char* ip = argv[1]; int port = atoi(argv[2]); int backlog = atoi(argv[3]); std::cout << "ip=" << ip << " port="<<port << " backlog=" << backlog << std::endl; int fd; int check_ret; fd = socket(PF_INET,SOCK_STREAM , 0); assert(fd >= 0); struct sockaddr_in address; bzero(&address,sizeof(address)); //轉換成網絡地址 address.sin_port = htons(port); address.sin_family = AF_INET; //地址轉換 inet_pton(AF_INET, ip, &address.sin_addr); //設置socket buffer大小 int recvbuf = 4096; int len = sizeof( recvbuf ); setsockopt( fd, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf ) ); getsockopt( fd, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len ); printf( "the receive buffer size after settting is %d\n", recvbuf ); //綁定ip和端口 check_ret = bind(fd,(struct sockaddr*)&address,sizeof(address)); assert(check_ret >= 0); //創建監聽隊列,用來存放待處理的客戶連接 check_ret = listen(fd, backlog); assert(check_ret >= 0); struct sockaddr_in addressClient; socklen_t clientLen = sizeof(addressClient); //接受連接,阻塞函數 int connfd = accept(fd, (struct sockaddr*)&addressClient, &clientLen); if(connfd < 0){ std::cout << "accept error"; }else{ //打印客戶端信息 char showData[INET_ADDRSTRLEN]; std::cout <<inet_ntop(AF_INET,&addressClient.sin_addr,showData,INET_ADDRSTRLEN)<<":" <<ntohs(addressClient.sin_port)<<std::endl; //接受數據 const int BUF_LEN = 1024; char sockBuf[BUF_LEN]; size_t ret; memset(sockBuf, '\0', BUF_LEN); ret = recv(connfd, sockBuf, BUF_LEN-1, 0); printf("ret=%ld,msg=%s\n",ret,sockBuf); memset(sockBuf, '\0', BUF_LEN); ret = recv(connfd, sockBuf, BUF_LEN-1, MSG_OOB); printf("ret=%ld,msg=%s\n",ret,sockBuf); memset(sockBuf, '\0', BUF_LEN); ret = recv(connfd, sockBuf, BUF_LEN-1, 0); printf("ret=%ld,msg=%s\n",ret,sockBuf); //獲取本地socket信息 struct sockaddr_in tmpAddress; clientLen = sizeof(tmpAddress); getsockname(fd, (struct sockaddr*)&tmpAddress, &clientLen); std::cout <<inet_ntop(AF_INET,&tmpAddress.sin_addr,showData,INET_ADDRSTRLEN)<<":" <<ntohs(tmpAddress.sin_port)<<std::endl; //獲取遠端socket信息 getpeername(connfd,(struct sockaddr*)&tmpAddress, &clientLen ); std::cout <<inet_ntop(AF_INET,&tmpAddress.sin_addr,showData,INET_ADDRSTRLEN)<<":" <<ntohs(tmpAddress.sin_port)<<std::endl; close(connfd); } close(fd); }
TCP CLIENT:
// // main.cpp // linux_socket_api_client // // Created by bikang on 16/11/2. // Copyright (c) 2016年 bikang. All rights reserved. // #include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> #include <assert.h> #include <stdio.h> #include <string.h> void tserver(int argc, const char * argv[]); int main(int argc, const char * argv[]) { tserver(argc,argv); return 0; } void tserver(int argc, const char * argv[]){ std::cout << "t server" << std::endl; if(argc < 3){ exit(-1); } const char* ip = argv[1]; int port = atoi(argv[2]); int backlog = atoi(argv[3]); std::cout << "ip=" << ip << " port="<<port << " backlog=" << backlog << std::endl; int fd; int check_ret; fd = socket(PF_INET,SOCK_STREAM , 0); assert(fd >= 0); int sendbuf = 4096; int len = sizeof( sendbuf ); setsockopt( fd, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof( sendbuf ) ); getsockopt( fd, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len ); printf( "the send buffer size after settting is %d\n", sendbuf ); struct sockaddr_in address; bzero(&address,sizeof(address)); //轉換成網絡地址 address.sin_port = htons(port); address.sin_family = AF_INET; //地址轉換 inet_pton(AF_INET, ip, &address.sin_addr); check_ret = connect(fd, (struct sockaddr*) &address, sizeof(address)); assert(check_ret >= 0); //發送數據 const char* oob_data = "abc"; const char* normal_data = "my boy!"; send(fd, normal_data, strlen(normal_data), 0); send(fd, oob_data, strlen(oob_data), MSG_OOB); send(fd, normal_data, strlen(normal_data), 0); close(fd); }
UDP SERVER:
#include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> #include <assert.h> #include <stdio.h> #include <string.h> //using namespace std; #define BUFFER_SIZE 1024 void tsocket(int argc, const char * argv[]); int main(int argc, const char * argv[]) { tsocket(argc,argv); return 0; } void tsocket(int argc, const char * argv[]){ if(argc < 3){ exit(-1); } const char* ip = argv[1]; int port = atoi(argv[2]); int backlog = atoi(argv[3]); std::cout << "ip=" << ip << " port="<<port << " backlog=" << backlog << std::endl; int fd; int check_ret; fd = socket(PF_INET,SOCK_DGRAM , 0); assert(fd >= 0); struct sockaddr_in address; bzero(&address,sizeof(address)); //轉換成網絡地址 address.sin_port = htons(port); address.sin_family = AF_INET; //地址轉換 inet_pton(AF_INET, ip, &address.sin_addr); //綁定ip和端口 check_ret = bind(fd,(struct sockaddr*)&address,sizeof(address)); assert(check_ret >= 0); while(1){ char buffer[BUFFER_SIZE]; struct sockaddr_in addressClient; socklen_t clientLen = sizeof(addressClient); memset(buffer, '\0', BUFFER_SIZE); //獲取信息 if(recvfrom(fd, buffer, BUFFER_SIZE-1,0,(struct sockaddr*)&addressClient, &clientLen) == -1) { perror("Receive Data Failed:"); exit(1); } printf("buffer=%s\n", buffer); } close(fd); }
UDP CLIENT:
// // main.cpp // linux_socket_api_client // // Created by bikang on 16/11/2. // Copyright (c) 2016年 bikang. All rights reserved. // #include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> #include <assert.h> #include <stdio.h> #include <string.h> void tserver(int argc, const char * argv[]); int main(int argc, const char * argv[]) { tserver(argc,argv); return 0; } void tserver(int argc, const char * argv[]){ std::cout << "t server" << std::endl; if(argc < 3){ exit(-1); } const char* ip = argv[1]; int port = atoi(argv[2]); int backlog = atoi(argv[3]); std::cout << "ip=" << ip << " port="<<port << " backlog=" << backlog << std::endl; int fd; int check_ret; fd = socket(PF_INET,SOCK_DGRAM , 0); assert(fd >= 0); struct sockaddr_in address; bzero(&address,sizeof(address)); //轉換成網絡地址 address.sin_port = htons(port); address.sin_family = AF_INET; //地址轉換 inet_pton(AF_INET, ip, &address.sin_addr); //發送數據 const char* normal_data = "my boy!"; if(sendto(fd, normal_data, strlen(normal_data),0,(struct sockaddr*)&address,sizeof(address)) < 0) { perror("Send File Name Failed:"); exit(1); } close(fd); }
另附:
linux網絡編程常用頭文件:
sys/types.h:數據類型定義
sys/socket.h:提供socket函數及數據結構
netinet/in.h:定義數據結構sockaddr_in
arpa/inet.h:提供IP地址轉換函數
netdb.h:提供設置及獲取域名的函數
sys/ioctl.h:提供對I/O控制的函數
sys/poll.h:提供socket等待測試機制的函數
其他在網絡程序中常見的頭文件
unistd.h:提供通用的文件、目錄、程序及進程操作的函數
errno.h:提供錯誤號errno的定義,用於錯誤處理
fcntl.h:提供對文件控制的函數
time.h:提供有關時間的函數
crypt.h:提供使用DES加密算法的加密函數
pwd.h:提供對/etc/passwd文件訪問的函數
shadow.h:提供對/etc/shadow文件訪問的函數
pthread.h:提供多線程操作的函數
signal.h:提供對信號操作的函數
sys/wait.h、sys/ipc.h、sys/shm.h:提供進程等待、進程間通訊(IPC)及共享內存的函數
在編寫網絡程序時,可以直接使用下面這段頭文件代碼
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <fcntl.h>
#include <fcntl.h>
涉及到用戶權限及密碼驗證問題時加入如下語句:
#include <shadow.h>
#include <crypt.h>
#include <pwd.h>
需要注意的是,應該在編譯時鏈接加密算法庫,即增加編譯選項:
-lcrypt
涉及到文件及時間操作加入如下語句:
#include <sys/time.h>
#include <utime.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/file.h>
涉及到多進程操作時加入如下語句:
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
涉及到多線程操作時加入如下語句:
#include <pthread.h>
#include <sys/poll.h>
需要注意的是,應該在編譯時鏈接線程庫,即增加編譯選項:-lthread