日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux 网络编程四(socket多线程升级版)

發布時間:2024/8/26 linux 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 网络编程四(socket多线程升级版) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
//網絡編程--客戶端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h>#include <sys/types.h> #include <sys/socket.h> #include <pthread.h> #include <netinet/in.h> #include <arpa/inet.h>/*強調:當客戶端連接服務器時,服務器會產生一個新的文件描述符(套接字)與客戶端交互,這個新的套接字不是服務器端的監聽套接字套接字是全雙工的,在一個網絡管道中的兩端,每端都可以進行讀寫操作。*/typedef struct _recvmodel {int st;struct sockaddr_in * addr; } RecvModel;//send message void * send_thread(void *arg) {if (arg == NULL){printf("param is not allow NULL!\n");return NULL;}int st = *(int *) arg;char buf[1024] = { 0 };while (1){read(STDIN_FILENO, buf, sizeof(buf));if (send(st, buf, strlen(buf), 0) == -1){printf("send failed ! error message %s\n", strerror(errno));return NULL;}memset(buf, 0, sizeof(buf));}return NULL; }//recv message void * recv_thread(void * arg) {if (arg == NULL){printf("param is not allow NULL!\n");return NULL;}RecvModel * model = (RecvModel *) arg;int flag = 0;char buf[1024] = { 0 };while (1){flag = recv(model->st, buf, sizeof(buf), 0);if (flag == 0){printf("對方已經關閉連接!\n");return NULL;} else if (flag == -1){printf("recv failed ! error message : %s\n", strerror(errno));return NULL;}printf("from %s:%s", inet_ntoa(model->addr->sin_addr), buf);memset(buf, 0, sizeof(buf));}return NULL; }int main(int arg, char *args[]) {//打開socketint st = socket(AF_INET, SOCK_STREAM, 0);if (st == -1){printf("open socket failed! error message:%s\n", strerror(errno));return -1;}//定義IP地址結構struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));//設置TCP/IP連接addr.sin_family=AF_INET;//設置端口號addr.sin_port = htons(8080);//設置允許連接地址addr.sin_addr.s_addr = inet_addr("192.168.1.102");//connect serverint numx = connect(st, (struct sockaddr *) &addr, sizeof(addr));if (numx == -1){printf("connect server failed ! error message :%s\n", strerror(errno));goto END;}RecvModel model;model.st = st;model.addr = &addr;//開啟多線程--線程1接收消息,線程2發送消息 pthread_t thr1, thr2;if (pthread_create(&thr1, NULL, send_thread, &st) != 0){printf("create thread failed ! \n");goto END;}if (pthread_create(&thr2, NULL, recv_thread, &model) != 0){printf("create thread failed ! \n");goto END;}pthread_join(thr1, NULL);pthread_join(thr2, NULL);END: close(st);return 0; } //網絡編程--服務端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h>#include <sys/types.h> #include <sys/socket.h> #include <pthread.h> #include <netinet/in.h> #include <arpa/inet.h>typedef struct _recvmodel {int st;struct sockaddr_in * addr; } RecvModel;//send message void * send_thread(void *arg) {if (arg == NULL){printf("param is not allow NULL!\n");return NULL;}int st = *(int *) arg;char buf[1024] = { 0 };while (1){read(STDIN_FILENO, buf, sizeof(buf));if (send(st, buf, strlen(buf), 0) == -1){printf("send failed ! error message %s\n", strerror(errno));return NULL;}memset(buf, 0, sizeof(buf));}return NULL; }//recv message void * recv_thread(void * arg) {if (arg == NULL){printf("param is not allow NULL!\n");return NULL;}RecvModel * model = (RecvModel *) arg;int flag = 0;char buf[1024] = { 0 };while (1){flag = recv(model->st, buf, sizeof(buf), 0);if (flag == 0){printf("對方已經關閉連接!\n");return NULL;} else if (flag == -1){printf("recv failed ! error message : %s\n", strerror(errno));return NULL;}printf("from %s:%s", inet_ntoa(model->addr->sin_addr), buf);memset(buf, 0, sizeof(buf));}return NULL; }int main(int arg, char *args[]) {//short port = atoi(args[1]);//打開socketint st = socket(AF_INET, SOCK_STREAM, 0);if (st == -1){printf("open socket failed! error message:%s\n", strerror(errno));return -1;}//設置系統地址可重用int on = 1;if (setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1){printf("setsockpot failed ! error message %s\n", strerror(errno));goto END;}//定義IP地址結構struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));//設置TCP/IP連接addr.sin_family = AF_INET;//設置端口號addr.sin_port = htons(8080);//設置允許連接地址addr.sin_addr.s_addr = htonl(INADDR_ANY);//bind ipif (bind(st, (struct sockaddr *) &addr, sizeof(addr)) == -1){printf("bind ip failed ! error message :%s\n", strerror(errno));goto END;}//監聽連接if (listen(st, 20) == -1){printf("listen failed ! error message :%s\n", strerror(errno));goto END;}//接收客戶端連接(阻塞)struct sockaddr_in client_addr;memset(&client_addr, 0, sizeof(client_addr));socklen_t client_addrlen = sizeof(client_addr);
//強調:這里的client_addrlen并不是為了在函數中設置client_addrlen的值,而是通過client_addrlen的值來判斷client_addr是一個什么類型的結構,
//所以這里client_addrlen設置為0是錯誤的,必須是struct sockaddr_in這個結構的大小,不然返回值不正確
int client_st = accept(st, (struct sockaddr *) &client_addr,&client_addrlen);if (client_st == -1){printf("accept failed ! error message :%s\n", strerror(errno));goto END;}RecvModel model;model.st = client_st;model.addr = &client_addr;printf("accept by=%s\n",inet_ntoa(client_addr.sin_addr));//開啟多線程--線程1接收消息,線程2發送消息 pthread_t thr1, thr2;if (pthread_create(&thr1, NULL, send_thread, &client_st) != 0){printf("create thread failed ! \n");goto END;}if (pthread_create(&thr2, NULL, recv_thread, &model) != 0){printf("create thread failed ! \n");goto END;}pthread_join(thr1, NULL);pthread_join(thr2, NULL);//關閉客戶端管道 close(client_st);END: close(st);return 0; } .SUFFIXES:.c .o CC=gcc SRCS1=mserver.c SRCS2=mclient.c OBJS1=$(SRCS1:.c=.o) OBJS2=$(SRCS2:.c=.o) EXEC1=mserv EXEC2=mclistart:$(OBJS1) $(OBJS2)$(CC) -o $(EXEC1) $(OBJS1) -lpthread$(CC) -o $(EXEC2) $(OBJS2) -lpthread@echo "^_^ ------ OK ------ ^_^" .c.o:$(CC) -Wall -g -o $@ -c $< clean:rm -f $(OBJS1)rm -f $(OBJS2)rm -f $(EXEC1)rm -f $(EXEC2) 小結:這段升級版程序花費3小時,出現一個錯誤提示:"?Transport endpoint is not connected",我仔細查找資料,
網上說是socket套接字不對,可我程序中套接字是正確的,
我沒有辦法,但是我有一個成功的程序,就是第一版socket程序,我將原來的socket程序復制到我的新程序中,一句句替換,終于發現這個問題
問題:我缺少addr.sin_family = AF_INET;//將網絡地址類型設置為TCP/IP協議;這句代碼。缺少這段代碼是導致報錯的主要原因。
另外注意我代碼中強調的內容--網絡管道是全雙工的

?

轉載于:https://www.cnblogs.com/zhanggaofeng/p/5877617.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的Linux 网络编程四(socket多线程升级版)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。