linux:C++的socket編程

  基本的局域網聊天

  局域網聊天TCP服務端:

運行下面代碼

#include #include #include #include #include #include #include #include #include #include #include #include #definePORT 7000#defineQUEUE 20int conn;void thread_task() {

}int main() {

? ? //printf("%d\n",AF_INET);

? ? //printf("%d\n",SOCK_STREAM);intss = socket(AF_INET, SOCK_STREAM,0);

? ? //printf("%d\n",ss);struct sockaddr_in server_sockaddr;

? ? server_sockaddr.sin_family = AF_INET;

? ? server_sockaddr.sin_port = htons(PORT);

? ? //printf("%d\n",INADDR_ANY);server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

? ? if(bind(ss, (structsockaddr* ) &server_sockaddr,sizeof(server_sockaddr))==-1) {

? ? ? ? perror("bind");

? ? ? ? exit(1);

? ? }

? ? if(listen(ss, QUEUE) == -1) {

? ? ? ? perror("listen");

? ? ? ? exit(1);

? ? }

? ? struct sockaddr_in client_addr;

? ? socklen_t length =sizeof(client_addr);

? ? ///成功返回非負描述字,出錯返回-1conn = accept(ss, (structsockaddr*)&client_addr, &length);

? ? if( conn <0 ) {

? ? ? ? perror("connect");

? ? ? ? exit(1);

? ? }

? ? charbuffer[1024];

? ? //創建另外一個線程

? ? //std::thread t(thread_task);

? ? //t.join();

? ? //char buf[1024];

? ? //主線程while(1) {

? ? ? ? // memset(buf, 0 ,sizeof(buf));

? ? ? ? // if(fgets(buf, sizeof(buf),stdin) != NULL) {

? ? ? ? //? ? send(conn, buf, sizeof(buf), 0);? ?

? ? ? ? // }? ? ? ? memset(buffer, 0,sizeof(buffer));

? ? ? ? intlen = recv(conn, buffer,sizeof(buffer),0);

? ? ? ? if(strcmp(buffer,"exit\n") ==0)break;

? ? ? ? printf("%s", buffer);

? ? ? ? //必須要有返回數據, 這樣才算一個完整的請求send(conn, buffer, len ,0);

? ? }

? ? close(conn);

? ? close(ss);

? ? return0;

}

  局域網聊天TCP客戶端:

運行下面代碼

#include #include #include #include #include #include #include #include #include #include #defineMYPORT? 7000#defineBUFFER_SIZE 1024int main()

{

? ? ///定義sockfdintsock_cli = socket(AF_INET,SOCK_STREAM,0);

? ? ///定義sockaddr_instruct sockaddr_in servaddr;

? ? memset(&servaddr,0,sizeof(servaddr));

? ? servaddr.sin_family = AF_INET;

? ? servaddr.sin_port = htons(MYPORT);///服務器端口servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");///服務器ip//連接服務器,成功返回0,錯誤返回-1if(connect(sock_cli, (structsockaddr *)&servaddr,sizeof(servaddr)) <0)

? ? {

? ? ? ? perror("connect");

? ? ? ? exit(1);

? ? }

? ? char sendbuf[BUFFER_SIZE];

? ? char recvbuf[BUFFER_SIZE];

? ? while(fgets(sendbuf,sizeof(sendbuf), stdin) != NULL)

? ? {

? ? ? ? send(sock_cli, sendbuf, strlen(sendbuf),0);///發送if(strcmp(sendbuf,"exit\n")==0)

? ? ? ? ? ? break;

? ? ? ? recv(sock_cli, recvbuf, sizeof(recvbuf),0);///接收? ? ? ? fputs(recvbuf, stdout);

? ? ? ? memset(sendbuf, 0,sizeof(sendbuf));

? ? ? ? memset(recvbuf, 0,sizeof(recvbuf));

? ? }

? ? close(sock_cli);

? ? return0;

}


回到頂部

客戶端服務端雙向異步聊天源碼

  以上的局域網聊天應用有一個很重要的缺點, 服務器只能顯示客戶端發送的消息, 卻無法給客戶端發送消息, 這個很尷尬;

  通過使用C中的select()函數, 實現一個異步聊天工具:

  異步聊天服務端代碼:

運行下面代碼

#include #include #include #include #include #include #include #include #include #include #include #definePORT 7000#defineQUEUE 20int main() {

? ? fd_set rfds;

? ? struct timeval tv;

? ? int retval, maxfd;

? ? intss = socket(AF_INET, SOCK_STREAM,0);

? ? struct sockaddr_in server_sockaddr;

? ? server_sockaddr.sin_family = AF_INET;

? ? server_sockaddr.sin_port = htons(PORT);

? ? //printf("%d\n",INADDR_ANY);server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

? ? if(bind(ss, (structsockaddr* ) &server_sockaddr,sizeof(server_sockaddr))==-1) {

? ? ? ? perror("bind");

? ? ? ? exit(1);

? ? }

? ? if(listen(ss, QUEUE) == -1) {

? ? ? ? perror("listen");

? ? ? ? exit(1);

? ? }

? ? struct sockaddr_in client_addr;

? ? socklen_t length =sizeof(client_addr);

? ? ///成功返回非負描述字,出錯返回-1intconn = accept(ss, (structsockaddr*)&client_addr, &length);

? ? if( conn <0 ) {

? ? ? ? perror("connect");

? ? ? ? exit(1);

? ? }

? ? while(1) {

? ? ? ? /*把可讀文件描述符的集合清空*/? ? ? ? FD_ZERO(&rfds);

? ? ? ? /*把標準輸入的文件描述符加入到集合中*/? ? ? ? FD_SET(0, &rfds);

? ? ? ? maxfd =0;

? ? ? ? /*把當前連接的文件描述符加入到集合中*/? ? ? ? FD_SET(conn, &rfds);

? ? ? ? /*找出文件描述符集合中最大的文件描述符*/if(maxfd < conn)

? ? ? ? ? ? maxfd = conn;

? ? ? ? /*設置超時時間*/? ? ? ? tv.tv_sec =5;

? ? ? ? tv.tv_usec =0;

? ? ? ? /*等待聊天*/? ? ? ? retval =select(maxfd+1, &rfds, NULL, NULL, &tv);

? ? ? ? if(retval == -1){

? ? ? ? ? ? printf("select出錯,客戶端程序退出\n");

? ? ? ? ? ? break;

? ? ? ? }elseif(retval ==0){

? ? ? ? ? ? printf("服務端沒有任何輸入信息,并且客戶端也沒有信息到來,waiting...\n");

? ? ? ? ? ? continue;

? ? ? ? }else{

? ? ? ? ? ? /*客戶端發來了消息*/if(FD_ISSET(conn,&rfds)){

? ? ? ? ? ? ? ? charbuffer[1024];? ?

? ? ? ? ? ? ? ? memset(buffer, 0,sizeof(buffer));

? ? ? ? ? ? ? ? intlen = recv(conn, buffer,sizeof(buffer),0);

? ? ? ? ? ? ? ? if(strcmp(buffer,"exit\n") ==0)break;

? ? ? ? ? ? ? ? printf("%s", buffer);

? ? ? ? ? ? ? ? //send(conn, buffer, len , 0);把數據回發給客戶端? ? ? ? ? ? }

? ? ? ? ? ? /*用戶輸入信息了,開始處理信息并發送*/if(FD_ISSET(0, &rfds)){

? ? ? ? ? ? ? ? charbuf[1024];

? ? ? ? ? ? ? ? fgets(buf, sizeof(buf), stdin);

? ? ? ? ? ? ? ? //printf("you are send %s", buf);send(conn, buf,sizeof(buf),0);? ?

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? close(conn);

? ? close(ss);

? ? return0;

}

  異步聊天客戶端代碼:

運行下面代碼

#include #include #include #include #include #include #include #include #include #include #defineMYPORT? 7000#defineBUFFER_SIZE 1024int main()

{

? ? int sock_cli;

? ? fd_set rfds;

? ? struct timeval tv;

? ? int retval, maxfd;

? ? ///定義sockfdsock_cli = socket(AF_INET,SOCK_STREAM,0);

? ? ///定義sockaddr_instruct sockaddr_in servaddr;

? ? memset(&servaddr,0,sizeof(servaddr));

? ? servaddr.sin_family = AF_INET;

? ? servaddr.sin_port = htons(MYPORT);///服務器端口servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");///服務器ip//連接服務器,成功返回0,錯誤返回-1if(connect(sock_cli, (structsockaddr *)&servaddr,sizeof(servaddr)) <0)

? ? {

? ? ? ? perror("connect");

? ? ? ? exit(1);

? ? }

? ? while(1){

? ? ? ? /*把可讀文件描述符的集合清空*/? ? ? ? FD_ZERO(&rfds);

? ? ? ? /*把標準輸入的文件描述符加入到集合中*/? ? ? ? FD_SET(0, &rfds);

? ? ? ? maxfd =0;

? ? ? ? /*把當前連接的文件描述符加入到集合中*/? ? ? ? FD_SET(sock_cli, &rfds);

? ? ? ? /*找出文件描述符集合中最大的文件描述符*/if(maxfd < sock_cli)

? ? ? ? ? ? maxfd = sock_cli;

? ? ? ? /*設置超時時間*/? ? ? ? tv.tv_sec =5;

? ? ? ? tv.tv_usec =0;

? ? ? ? /*等待聊天*/? ? ? ? retval =select(maxfd+1, &rfds, NULL, NULL, &tv);

? ? ? ? if(retval == -1){

? ? ? ? ? ? printf("select出錯,客戶端程序退出\n");

? ? ? ? ? ? break;

? ? ? ? }elseif(retval ==0){

? ? ? ? ? ? printf("客戶端沒有任何輸入信息,并且服務器也沒有信息到來,waiting...\n");

? ? ? ? ? ? continue;

? ? ? ? }else{

? ? ? ? ? ? /*服務器發來了消息*/if(FD_ISSET(sock_cli,&rfds)){

? ? ? ? ? ? ? ? char recvbuf[BUFFER_SIZE];

? ? ? ? ? ? ? ? int len;

? ? ? ? ? ? ? ? len = recv(sock_cli, recvbuf,sizeof(recvbuf),0);

? ? ? ? ? ? ? ? printf("%s", recvbuf);

? ? ? ? ? ? ? ? memset(recvbuf, 0,sizeof(recvbuf));

? ? ? ? ? ? }

? ? ? ? ? ? /*用戶輸入信息了,開始處理信息并發送*/if(FD_ISSET(0, &rfds)){

? ? ? ? ? ? ? ? char sendbuf[BUFFER_SIZE];

? ? ? ? ? ? ? ? fgets(sendbuf, sizeof(sendbuf), stdin);

? ? ? ? ? ? ? ? send(sock_cli, sendbuf, strlen(sendbuf),0);//發送memset(sendbuf,0,sizeof(sendbuf));

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? close(sock_cli);

? ? return0;

}


回到頂部

局域網內服務端和有限個客戶端聊天源碼

?  以上的局域網聊天只能支持一個用戶, 我們還要改改, 必須是支持多用戶的聊天室:

  局域網TCP多人聊天服務端代碼:

運行下面代碼

#include #include #include #include #include #include #include #include #include #include #include #include #definePORT 7000#defineQUEUE 20int ss;struct sockaddr_in client_addr;

socklen_t length =sizeof(client_addr);intconns[2] = {};intz =0;void thread_fn() {

? ? //成功返回非負描述字,出錯返回-1intconn = accept(ss, (structsockaddr*)&client_addr, &length);

? ? if( conn <0 ) {

? ? ? ? perror("connect");

? ? ? ? exit(1);

? ? }

? ? //把連接保存到臨時數組中;conns[z] = conn;

? ? z++;

? ? fd_set rfds;

? ? struct timeval tv;

? ? int retval, maxfd;

? ? while(1) {

? ? ? ? /*把可讀文件描述符的集合清空*/? ? ? ? FD_ZERO(&rfds);

? ? ? ? /*把標準輸入的文件描述符加入到集合中*/? ? ? ? FD_SET(0, &rfds);

? ? ? ? maxfd =0;

? ? ? ? /*把當前連接的文件描述符加入到集合中*/? ? ? ? FD_SET(conn, &rfds);

? ? ? ? /*找出文件描述符集合中最大的文件描述符*/if(maxfd < conn)

? ? ? ? ? ? maxfd = conn;

? ? ? ? /*設置超時時間*/? ? ? ? tv.tv_sec =5;

? ? ? ? tv.tv_usec =0;

? ? ? ? /*等待聊天*/? ? ? ? retval =select(maxfd+1, &rfds, NULL, NULL, &tv);

? ? ? ? if(retval == -1){

? ? ? ? ? ? printf("select出錯,客戶端程序退出\n");

? ? ? ? ? ? break;

? ? ? ? }elseif(retval ==0){

? ? ? ? ? ? printf("服務端沒有任何輸入信息,并且客戶端也沒有信息到來,waiting...\n");

? ? ? ? ? ? continue;

? ? ? ? }else{

? ? ? ? ? ? /*客戶端發來了消息*/if(FD_ISSET(conn,&rfds)){

? ? ? ? ? ? ? ? charbuffer[1024];? ?

? ? ? ? ? ? ? ? memset(buffer, 0,sizeof(buffer));

? ? ? ? ? ? ? ? intlen = recv(conn, buffer,sizeof(buffer),0);

? ? ? ? ? ? ? ? if(strcmp(buffer,"exit\n") ==0)break;

? ? ? ? ? ? ? ? printf("%s", buffer);

? ? ? ? ? ? ? ? //send(conn, buffer, len , 0);把數據回發給客戶端? ? ? ? ? ? }

? ? ? ? ? ? /*用戶輸入信息了,開始處理信息并發送*/if(FD_ISSET(0, &rfds)){

? ? ? ? ? ? ? ? charbuf[1024];

? ? ? ? ? ? ? ? fgets(buf, sizeof(buf), stdin);

? ? ? ? ? ? ? ? //printf("you are send %s", buf);for(inti=0; i

? ? ? ? ? ? ? ? ? ? send(conns[i], buf, sizeof(buf),0);

? ? ? ? ? ? ? ? }? ?

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? close(conn);

}voidthread_select(int conn) {

}int main() {

? ? ss = socket(AF_INET, SOCK_STREAM,0);

? ? struct sockaddr_in server_sockaddr;

? ? server_sockaddr.sin_family = AF_INET;

? ? server_sockaddr.sin_port = htons(PORT);

? ? //printf("%d\n",INADDR_ANY);server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

? ? if(bind(ss, (structsockaddr* ) &server_sockaddr,sizeof(server_sockaddr))==-1) {

? ? ? ? perror("bind");

? ? ? ? exit(1);

? ? }

? ? if(listen(ss, QUEUE) == -1) {

? ? ? ? perror("listen");

? ? ? ? exit(1);

? ? }

? ? std::thread t(thread_fn);

? ? std::thread t1(thread_fn);

? ? t.join();

? ? t1.join();

? ? close(ss);

? ? return0;

}

  局域網TCP多人聊天客戶端代碼:

運行下面代碼

#include #include #include #include #include #include #include #include #include #include #defineMYPORT? 7000#defineBUFFER_SIZE 1024int main()

{

? ? int sock_cli;

? ? fd_set rfds;

? ? struct timeval tv;

? ? int retval, maxfd;

? ? ///定義sockfdsock_cli = socket(AF_INET,SOCK_STREAM,0);

? ? ///定義sockaddr_instruct sockaddr_in servaddr;

? ? memset(&servaddr,0,sizeof(servaddr));

? ? servaddr.sin_family = AF_INET;

? ? servaddr.sin_port = htons(MYPORT);///服務器端口servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");///服務器ip//連接服務器,成功返回0,錯誤返回-1if(connect(sock_cli, (structsockaddr *)&servaddr,sizeof(servaddr)) <0)

? ? {

? ? ? ? perror("connect");

? ? ? ? exit(1);

? ? }

? ? while(1){

? ? ? ? /*把可讀文件描述符的集合清空*/? ? ? ? FD_ZERO(&rfds);

? ? ? ? /*把標準輸入的文件描述符加入到集合中*/? ? ? ? FD_SET(0, &rfds);

? ? ? ? maxfd =0;

? ? ? ? /*把當前連接的文件描述符加入到集合中*/? ? ? ? FD_SET(sock_cli, &rfds);

? ? ? ? /*找出文件描述符集合中最大的文件描述符*/if(maxfd < sock_cli)

? ? ? ? ? ? maxfd = sock_cli;

? ? ? ? /*設置超時時間*/? ? ? ? tv.tv_sec =5;

? ? ? ? tv.tv_usec =0;

? ? ? ? /*等待聊天*/? ? ? ? retval =select(maxfd+1, &rfds, NULL, NULL, &tv);

? ? ? ? if(retval == -1){

? ? ? ? ? ? printf("select出錯,客戶端程序退出\n");

? ? ? ? ? ? break;

? ? ? ? }elseif(retval ==0){

? ? ? ? ? ? printf("客戶端沒有任何輸入信息,并且服務器也沒有信息到來,waiting...\n");

? ? ? ? ? ? continue;

? ? ? ? }else{

? ? ? ? ? ? /*服務器發來了消息*/if(FD_ISSET(sock_cli,&rfds)){

? ? ? ? ? ? ? ? char recvbuf[BUFFER_SIZE];

? ? ? ? ? ? ? ? int len;

? ? ? ? ? ? ? ? len = recv(sock_cli, recvbuf,sizeof(recvbuf),0);

? ? ? ? ? ? ? ? printf("%s", recvbuf);

? ? ? ? ? ? ? ? memset(recvbuf, 0,sizeof(recvbuf));

? ? ? ? ? ? }

? ? ? ? ? ? /*用戶輸入信息了,開始處理信息并發送*/if(FD_ISSET(0, &rfds)){

? ? ? ? ? ? ? ? char sendbuf[BUFFER_SIZE];

? ? ? ? ? ? ? ? fgets(sendbuf, sizeof(sendbuf), stdin);

? ? ? ? ? ? ? ? send(sock_cli, sendbuf, strlen(sendbuf),0);//發送memset(sendbuf,0,sizeof(sendbuf));

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? close(sock_cli);

? ? return0;

}


回到頂部

完美異步聊天服務端和客戶端源碼

  以上的多客戶聊天不是很好, 因為只允許兩個客戶端連接, 體驗非常差, 如果支持無限個客戶端聊天的話那該多好啊, 哈哈, 這個也是可以的, 我們只要使用c++的list即可, 它是可以自增的數組(其實算是鏈表), 引用 頭文件<list>即可:

  無限個客戶聊天的 服務端代碼:

運行下面代碼

#include #include #include #include #include #include #include #include #include #include #include #include #include #definePORT 7000#defineIP "127.0.0.1"int s;struct sockaddr_in servaddr;

socklen_t len;

std::list li;void getConn() {

? ? while(1){

? ? ? ? intconn = accept(s, (structsockaddr*)&servaddr, &len);

? ? ? ? li.push_back(conn);

? ? ? ? printf("%d\n", conn);

? ? }

}void getData() {

? ? struct timeval tv;

? ? tv.tv_sec =2;

? ? tv.tv_usec =0;

? ? while(1) {

? ? ? ? std::list::iterator it;

? ? ? ? for(it=li.begin(); it!=li.end(); ++it){? ? ? ? ? ?

? ? ? ? ? ? fd_set rfds;? ?

? ? ? ? ? ? FD_ZERO(&rfds);

? ? ? ? ? ? intmaxfd =0;

? ? ? ? ? ? intretval =0;

? ? ? ? ? ? FD_SET(*it, &rfds);

? ? ? ? ? ? if(maxfd < *it){

? ? ? ? ? ? ? ? maxfd = *it;

? ? ? ? ? ? }

? ? ? ? ? ? retval =select(maxfd+1, &rfds, NULL, NULL, &tv);

? ? ? ? ? ? if(retval == -1){

? ? ? ? ? ? ? ? printf("select error\n");

? ? ? ? ? ? }elseif(retval ==0) {

? ? ? ? ? ? ? ? //printf("not message\n");}else{

? ? ? ? ? ? ? ? charbuf[1024];

? ? ? ? ? ? ? ? memset(buf, 0,sizeof(buf));

? ? ? ? ? ? ? ? intlen = recv(*it, buf,sizeof(buf),0);

? ? ? ? ? ? ? ? printf("%s", buf);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? sleep(1);

? ? }

}void sendMess() {

? ? while(1) {

? ? ? ? charbuf[1024];

? ? ? ? fgets(buf, sizeof(buf), stdin);

? ? ? ? //printf("you are send %s", buf);std::list::iterator it;

? ? ? ? for(it=li.begin(); it!=li.end(); ++it){

? ? ? ? ? ? send(*it, buf,sizeof(buf),0);

? ? ? ? }

? ? }

}int main() {

? ? //new sockets = socket(AF_INET, SOCK_STREAM,0);

? ? memset(&servaddr,0,sizeof(servaddr));

? ? servaddr.sin_family = AF_INET;

? ? servaddr.sin_port = htons(PORT);

? ? servaddr.sin_addr.s_addr = inet_addr(IP);

? ? if(bind(s, (structsockaddr* ) &servaddr,sizeof(servaddr))==-1) {

? ? ? ? perror("bind");

? ? ? ? exit(1);

? ? }

? ? if(listen(s,20) == -1) {

? ? ? ? perror("listen");

? ? ? ? exit(1);

? ? }

? ? len =sizeof(servaddr);

? ? //thread : while ==>> accpet? ? std::thread t(getConn);

? ? t.detach();

? ? //printf("done\n");

? ? //thread : input ==>> send? ? std::thread t1(sendMess);

? ? t1.detach();

? ? //thread : recv ==>> show? ? std::thread t2(getData);

? ? t2.detach();

? ? while(1){

? ? }

? ? return0;

}

  無限個客戶端連接的客戶端代碼:

運行下面代碼

#include #include #include #include #include #include #include #include #include #include #defineMYPORT? 7000#defineBUFFER_SIZE 1024int main()

{

? ? int sock_cli;

? ? fd_set rfds;

? ? struct timeval tv;

? ? int retval, maxfd;

? ? ///定義sockfdsock_cli = socket(AF_INET,SOCK_STREAM,0);

? ? ///定義sockaddr_instruct sockaddr_in servaddr;

? ? memset(&servaddr,0,sizeof(servaddr));

? ? servaddr.sin_family = AF_INET;

? ? servaddr.sin_port = htons(MYPORT);///服務器端口servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");///服務器ip//連接服務器,成功返回0,錯誤返回-1if(connect(sock_cli, (structsockaddr *)&servaddr,sizeof(servaddr)) <0)

? ? {

? ? ? ? perror("connect");

? ? ? ? exit(1);

? ? }

? ? while(1){

? ? ? ? /*把可讀文件描述符的集合清空*/? ? ? ? FD_ZERO(&rfds);

? ? ? ? /*把標準輸入的文件描述符加入到集合中*/? ? ? ? FD_SET(0, &rfds);

? ? ? ? maxfd =0;

? ? ? ? /*把當前連接的文件描述符加入到集合中*/? ? ? ? FD_SET(sock_cli, &rfds);

? ? ? ? /*找出文件描述符集合中最大的文件描述符*/if(maxfd < sock_cli)

? ? ? ? ? ? maxfd = sock_cli;

? ? ? ? /*設置超時時間*/? ? ? ? tv.tv_sec =5;

? ? ? ? tv.tv_usec =0;

? ? ? ? /*等待聊天*/? ? ? ? retval =select(maxfd+1, &rfds, NULL, NULL, &tv);

? ? ? ? if(retval == -1){

? ? ? ? ? ? printf("select出錯,客戶端程序退出\n");

? ? ? ? ? ? break;

? ? ? ? }elseif(retval ==0){

? ? ? ? ? ? printf("客戶端沒有任何輸入信息,并且服務器也沒有信息到來,waiting...\n");

? ? ? ? ? ? continue;

? ? ? ? }else{

? ? ? ? ? ? /*服務器發來了消息*/if(FD_ISSET(sock_cli,&rfds)){

? ? ? ? ? ? ? ? char recvbuf[BUFFER_SIZE];

? ? ? ? ? ? ? ? int len;

? ? ? ? ? ? ? ? len = recv(sock_cli, recvbuf,sizeof(recvbuf),0);

? ? ? ? ? ? ? ? printf("%s", recvbuf);

? ? ? ? ? ? ? ? memset(recvbuf, 0,sizeof(recvbuf));

? ? ? ? ? ? }

? ? ? ? ? ? /*用戶輸入信息了,開始處理信息并發送*/if(FD_ISSET(0, &rfds)){

? ? ? ? ? ? ? ? char sendbuf[BUFFER_SIZE];

? ? ? ? ? ? ? ? fgets(sendbuf, sizeof(sendbuf), stdin);

? ? ? ? ? ? ? ? send(sock_cli, sendbuf, strlen(sendbuf),0);//發送memset(sendbuf,0,sizeof(sendbuf));

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? close(sock_cli);

? ? return0;

}



局域網通過UDP實現服務端和客戶端的通信, UDP的服務端不需要執行listen函數accept函數

運行下面代碼

#include #include #include #include #include #include #include #definePORT_SERV 8888#defineBUFF_LEN 256voidudpserv_echo(ints,structsockaddr* client);int main() {

? ? int s;

? ? struct sockaddr_in addr_serv, addr_clie;

? ? s = socket(AF_INET, SOCK_DGRAM,0);

? ? memset(&addr_serv,0,sizeof(addr_serv));

? ? addr_serv.sin_family = AF_INET;

? ? addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);

? ? addr_serv.sin_port = htons(PORT_SERV);

? ? bind(s, (structsockaddr*)&addr_serv,sizeof(addr_serv));

? ? udpserv_echo(s, (structsockaddr*)&addr_clie);

? ? return0;

}voidudpserv_echo(ints,structsockaddr* client) {

? ? int n;

? ? char buff[BUFF_LEN];

? ? int len;

? ? //printf("%p\n",&recvfrom);while(1) {

? ? ? ? socklen_t length =sizeof(client);

? ? ? ? n = recvfrom(s, buff, BUFF_LEN,0, client, &length);

? ? ? ? printf("%s\n", buff);

? ? ? ? //strcpy(buff, "nice to see you");sendto(s, buff, n,0, client, len);

? ? }

}

UDP客戶端代碼, UDP客戶端不需要connect函數, 但是執行sendto的時候需要指定 sockfd描述符:

運行下面代碼

#include #include #include #include #include #include #definePORT_SERV 8888#defineBUFF_LEN 256voidudpclient_echo(ints,structsockaddr* serv) {

? ? char buff[BUFF_LEN];

? ? intlen =sizeof(*serv);

? ? while(fgets(buff, BUFF_LEN, stdin)!=NULL) {

? ? ? ? sendto(s, buff, BUFF_LEN, 0, serv, len);? ? ?

? ? }

}intmain(intargc ,char** argv) {

? ? int s;

? ? struct sockaddr_in addr_serv;

? ? s = socket(AF_INET, SOCK_DGRAM,0);

? ? memset(&addr_serv,0,sizeof(addr_serv));

? ? addr_serv.sin_family = AF_INET;

? ? //addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);addr_serv.sin_addr.s_addr = inet_addr(argv[1]);

? ? addr_serv.sin_port = htons(PORT_SERV);

? ? udpclient_echo(s, (structsockaddr*)&addr_serv);

? ? return0;

}

  獲取當前進程的ID:

運行下面代碼

#include #include #include intmain(void) {

? ? pid_t pid,ppid;

? ? pid = getpid();

? ? ppid = getppid();

? ? printf("pid is %d;\nppid is %d; \n",pid, ppid);

? ? return0;

}

  system語句的使用:

運行下面代碼

#include #include intmain(void) {

? ? int ret;

? ? ret = system("ping www.baidu.com");

? ? printf("%d\n", ret);

? ? return0;

}

回到頂部

C++定時器

  定時器, 這個是c++的語法, c的標準庫中沒有定時器:

運行下面代碼

#include //printf()#include //pause()#include //signal()#include //memset()#include //struct itimerval, setitimer()staticintcount =0;voidprintMes(int signo)

{

? ? printf("Get a SIGALRM, %d counts!\n", ++count);

}int main()

{

? ? intres =0;

? ? struct itimerval tick;


? ? signal(SIGALRM, printMes);

? ? memset(&tick,0,sizeof(tick));

? ? //Timeout to run first timetick.it_value.tv_sec =1;

? ? tick.it_value.tv_usec =0;

? ? //After first, the Interval time for clocktick.it_interval.tv_sec =1;

? ? tick.it_interval.tv_usec =0;

? ? setitimer(ITIMER_REAL, &tick, NULL);

? ? //if(setitimer(ITIMER_REAL, &tick, NULL) < 0)

? ? ? ? ? ? //printf("Set timer failed!\n");

? ? //When get a SIGALRM, the main process will enter another loop for pause()while(1)

? ? {

? ? }

? ? return0;

}

  select的使用,通過select可以實現定時器:

運行下面代碼

staticvoidsleep_ms(unsignedint secs){

? ? struct timeval tval;

? ? tval.tv_sec=secs/1000;

? ? tval.tv_usec=(secs*1000)%1000000;

? ? select(0,NULL,NULL,NULL,&tval);

}

回到頂部

select異步代碼

  通過select,實現socket可讀或者可寫的時候,然后再搞事情:

運行下面代碼

#include #include #include #include int main() {

? ? while(1) {

? ? ? ? fd_set rd;

? ? ? ? struct timeval tv;

? ? ? ? int err;

? ? ? ? FD_ZERO(&rd);

? ? ? ? FD_SET(0, &rd);

? ? ? ? tv.tv_sec =5;

? ? ? ? tv.tv_usec =0;

? ? ? ? err =select(1, &rd, NULL, NULL, &tv);

? ? ? ? if(err == -1) {

? ? ? ? ? ? perror("select error()\n");

? ? ? ? }elseif(err ==0) {

? ? ? ? ? ? printf("no data is avaliable now\n");

? ? ? ? }else{

? ? ? ? ? ? if(FD_ISSET(0, &rd)) {

? ? ? ? ? ? ? ? charbuf[1024];

? ? ? ? ? ? ? ? fgets(buf, sizeof(buf), stdin);

? ? ? ? ? ? ? ? printf("%s",buf);

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? return0;

}

回到頂部

pthead多線程

沒有參數的多線程 ,假設文件名字為:ph.c ,那么要通過?gcc ph.c -o ph -w -lphread?,進行編譯:

運行下面代碼

#include #include #include void*pfn() {

? ? printf("run\n");

}voidmain(intargc ,char*argv[] ) {

? ? pthread_t pid, pid2;

? ? pthread_create(&pid, NULL, pfn, NULL);

? ? pthread_join(pid, NULL);

}

  pthead多線程編程, 使用pthead實現子程, 并給子程傳遞參數:

運行下面代碼

#include #include #include #include #include #include void* start(void* args) {

? ? printf("sub thread ; the args is %d\n", *((int*)args));

? ? return NULL;

}intmain(void) {

? ? pthread_t pt;

? ? intret = -1;

? ? inttimes =3;

? ? intrun =2;

? ? ret = pthread_create(&pt, NULL, start, &run);

? ? if(ret !=0) {

? ? ? ? printf("create error\n");

? ? ? ? return1;

? ? }

? ? usleep(1);

? ? printf("main thread\n");

? ? pthread_join(pt, NULL);

? ? return0;

}


  獲取指定網卡的MAC地址和IP:

運行下面代碼

#include #include #include #include #include #include #include #include #include #include #include #include #include voidgetMac(char*MAC,char*str) {

? charifPath[256]="/sys/class/net/";//默認網卡路徑? ? strcat(ifPath , str);

? ? strcat(ifPath ,"/address");

? ? //打開這個設備FILE *ff = fopen(ifPath,"r");

? ? fread(MAC,1,17, ff);

? ? fclose(ff);

}

//根據網卡獲取ip的通用函數voidgetIp(unsignedchar*ip,char*itf) {

? ? int fd;

? ? struct ifreq ifr;

? ? in_addr tIP ;

? ? fd = socket(AF_INET, SOCK_DGRAM,0);//using ioctl get IP addressifr.ifr_addr.sa_family = AF_INET;

? ? strcpy(ifr.ifr_name , (char*)itf);

? ? ioctl(fd, SIOCGIFADDR, &ifr);

? ? close(fd);

? ? tIP =((structsockaddr_in *)&ifr.ifr_addr)->sin_addr;

? ? memcpy((char*)ip , &tIP ,sizeof(in_addr));

? ? printf("ip is %s", inet_ntoa(tIP));

}intmain(intargc,char*argv[]) {

? ? struct sockaddr_ll device;

? ? charNetInterface[10];

? ? strcpy(NetInterface, argv[1]);

? ? intindex = if_nametoindex ((constchar*)NetInterface);

? ? printf("index is %d\n", index);

? ? //get MAC, 要設置初始值charMAC[18]={0};

? ? charend[] ="0";

? ? getMac(MAC, argv[1]);

? ? printf("%s\n", MAC);

? ? unsigned charip[4];

? ? getIp(ip, argv[1]);

? ? printf("\n");

? ? return0;

}


  C, fork語句的使用, fork返回值為0時說明運行在拷貝線程中:

運行下面代碼

#include #include #include #include int main() {

? ? pid_t pid;

? ? pid = fork();

? ? if( -1== pid ) {

? ? ? ? printf("error \n");

? ? }elseif( pid ==0 ) {

? ? ? ? printf(" fork value %d ; parent id : %d ; fork id : %d\n ", pid, getppid(), getpid());

? ? }else{

? ? ? ? printf(" run in parent scope, pid is %d \n", getpid());

? ? }

? ? return0;

}

  通過使用fork,可以簡化服務端的代碼, 局域網聊天服務端代碼:

運行下面代碼

#include #include #include #include #include #include #include #include #include #include constintMAX_LINE =2048;constintPORT =6000;constintBACKLOG =10;constintLISTENQ =6666;constintMAX_CONNECT =20;int main() {

? ? struct sockaddr_in serAddr, cliAddr;

? ? int listenFd, connFd;

? ? pid_t childPid;

? ? char buf[MAX_LINE];

? ? socklen_t client;

? ? listenFd = socket(AF_INET, SOCK_STREAM,0);

? ? if(listenFd <0){

? ? ? ? perror("socket error");

? ? ? ? exit(1);

? ? }

? ? bzero(&serAddr,sizeof(serAddr));

? ? serAddr.sin_family = AF_INET;

? ? serAddr.sin_addr.s_addr = htonl(INADDR_ANY);

? ? serAddr.sin_port = htons(PORT);

? ? if(bind(listenFd, (structsockaddr*)&serAddr,sizeof(serAddr)) <0) {

? ? ? ? perror("bind error");

? ? ? ? exit(1);

? ? };

? ? if(listen(listenFd, LISTENQ) <0) {

? ? ? ? perror("listen error");

? ? ? ? exit(1);

? ? };

? ? ? ? printf("data");

? ? while(true) {

? ? ? ? client =sizeof(cliAddr);

? ? ? ? connFd = accept(listenFd, (structsockaddr*)&cliAddr, &client);

? ? ? ? if(connFd <0) {

? ? ? ? ? ? perror("accept error");

? ? ? ? ? ? exit(1);

? ? ? ? }

? ? ? ? childPid =fork();

? ? ? ? if(childPid ==0) {

? ? ? ? ? ? close(listenFd);

? ? ? ? ? ? char buf[MAX_LINE];

? ? ? ? ? ? while(read(connFd, buf, MAX_LINE) >0) {

? ? ? ? ? ? ? ? printf("data is %s", buf);

? ? ? ? ? ? ? ? memset(buf, 0,sizeof(buf));

? ? ? ? ? ? };

? ? ? ? }

? ? }

? ? close(listenFd);

? ? return0;

}

  客戶端代碼:

運行下面代碼

#include #include #include #include #include #include #include #include #include #include constintMAX_LINE =2048;constintPORT =6000;constintBACKLOG =10;constintLISTENQ =6666;constintMAX_CONNECT =20;intmain(intargc ,char**argv) {

? ? int sockFd;

? ? struct sockaddr_in serAddr;

? ? if( argc !=2) {

? ? ? ? perror("args error");

? ? ? ? exit(1);

? ? }

? ? sockFd = socket(AF_INET, SOCK_STREAM,0);

? ? if(sockFd <0) {

? ? ? ? perror("socket error");

? ? ? ? exit(1);

? ? }

? ? bzero(&serAddr,sizeof(serAddr));

? ? serAddr.sin_family = AF_INET;

? ? serAddr.sin_port = htons(PORT);

? ? printf("%s",argv[0]);

? ? //serAddr.sin_addr.s_addr = inet_addr(argv[1]);if(inet_pton(AF_INET , argv[1] , &serAddr.sin_addr) <0)

? ? {

? ? ? ? printf("inet_pton error for %s\n",argv[1]);

? ? ? ? exit(1);

? ? }

? ? if(connect(sockFd, (structsockaddr*)&serAddr,sizeof(serAddr)) <0) {

? ? ? ? perror("connect error");

? ? ? ? exit(1);

? ? };

? ? char sendLine[MAX_LINE];

? ? while(fgets(sendLine, MAX_LINE, stdin)!=NULL) {

? ? ? ? write(sockFd, sendLine, strlen(sendLine));

? ? }

? ? close(sockFd);

? ? return0;

}

?  socket服務端:

運行下面代碼

#include #include #include #include #include #include #include #defineQUEUE 10#defineSIZE 256int main() {

? ? //sock fd int fd;

? ? struct sockaddr_in saddr, caddr;

? ? fd = socket(AF_INET, SOCK_STREAM,0);

? ? if( fd<0 ){

? ? ? ? perror("socket error");

? ? ? ? exit(1);

? ? }

? ? bzero(&saddr ,sizeof(saddr));

? ? bzero(&caddr ,sizeof(caddr));

? ? saddr.sin_family = AF_INET;

? ? saddr.sin_port = htons(2000);

? ? saddr.sin_addr.s_addr = htonl(INADDR_ANY);

? ? //bind intbfd = bind(fd, (structsockaddr *)&saddr,sizeof(saddr));

? ? if( bfd<0 ){

? ? ? ? perror("bind error");

? ? ? ? exit(1);

? ? }

? ? //listenintlfd = listen(fd, QUEUE);

? ? if( lfd<0 ){

? ? ? ? perror("listen error");

? ? ? ? exit(1);

? ? }

? ? //acceptsocklen_t len =sizeof(caddr);

? ? intconn = accept(fd, (structsockaddr *)&caddr, &len);

? ? if(conn <0){

? ? ? ? perror("conn error");

? ? ? ? exit(1);

? ? }

? ? char buf[SIZE];

? ? while(read(conn, buf, SIZE) >0) {

? ? ? ? //readprintf("%s", buf);

? ? ? ? bzero(buf, SIZE);

? ? }

? ? close(fd);

? ? return0;

}

  socket客戶端:

運行下面代碼

#include #include #include #include #include #include #include #include #defineSIZE 256int main() {

? ? int fd;

? ? fd = socket(AF_INET, SOCK_STREAM,0);

? ? struct sockaddr_in saddr;

? ? bzero(&saddr,sizeof(saddr));

? ? saddr.sin_family = AF_INET;

? ? saddr.sin_port = htons(2000);

? ? saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

? ? int conn;

? ? conn = connect(fd, (structsockaddr*)&saddr,sizeof(saddr));

? ? if( conn<0 ) {

? ? ? ? perror("error");

? ? ? ? exit(1);

? ? }

? ? char buf[SIZE];

? ? while(fgets(buf, SIZE, stdin)!=NULL) {

? ? ? ? printf("%s", buf);

? ? ? ? write(fd, buf, SIZE);

? ? ? ? bzero(buf, SIZE);

? ? }

? ? return0;

}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容