I am writing a socket programming, one part is first send then receive, one part is receive then send.
The program work like this:
ThreadA: Send to Port 8000-> close socket -> get myport (portA) that i send -> listen to my port(portA)
ThreadB: Listen port 8000 -> Get the port when receive (portA)-> close socket -> send pack to same port (port A)
std::thread ThreadA,ThreadB; long share_port=8000; char share_addr[INET_ADDRSTRLEN]="127.0.0.1"; void send_then_receive(); void receive_then_send(); void send_then_receive(){ long myport = -1, receiver_port = share_port; SOCKET receive_then_send_A_Socket,receive_then_send_A_Socket_b,receive_then_send_B_Socket; //- Send to who i want struct sockaddr_in receive_then_send_B_Addr; receive_then_send_B_Addr.sin_family = AF_INET; inet_pton(AF_INET, share_addr, &receive_then_send_B_Addr.sin_addr.s_addr); receive_then_send_B_Addr.sin_port = htons((u_short)receiver_port); receive_then_send_B_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); while (connect(receive_then_send_B_Socket, (struct sockaddr *)&receive_then_send_B_Addr, sizeof(sockaddr_in)) == SOCKET_ERROR){ printf("\nConnect Fail in first response| Fail Code:%i\n", WSAGetLastError()); } send(receive_then_send_B_Socket, "4321", 5, 0); printf("[1]The port I want to send to:%ld\n",receiver_port); //- Check My Port socklen_t checkport_adr_len = sizeof(receive_then_send_B_Addr); if (getsockname(receive_then_send_B_Socket, (struct sockaddr *)&receive_then_send_B_Addr, &checkport_adr_len) == 0){ myport = ntohs(receive_then_send_B_Addr.sin_port); printf("[1]MyPort Check:%ld\n", myport); } close(receive_then_send_B_Socket); //- Then Recive sockaddr_in *receive_then_send_A_Addr = new sockaddr_in; receive_then_send_A_Addr->sin_family = AF_INET; receive_then_send_A_Addr->sin_addr.s_addr = INADDR_ANY; receive_then_send_A_Addr->sin_port = htons((u_short)myport); receive_then_send_A_Socket = socket(AF_INET, SOCK_STREAM, 0); bind(receive_then_send_A_Socket, (struct sockaddr *)receive_then_send_A_Addr, sizeof(struct sockaddr_in)); listen(receive_then_send_A_Socket, 1); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); receive_then_send_A_Socket_b = accept(receive_then_send_A_Socket, 0, 0); char* buffer_A= new char[100]; recv(receive_then_send_A_Socket_b, buffer_A, 100, 0); printf("[1]What I then receive: %s\n",buffer_A); close(receive_then_send_A_Socket); close(receive_then_send_A_Socket_b); } void receive_then_send(){ long myport = -1, receiver_port = -1; SOCKET receive_then_send_A_Socket,receive_then_send_A_Socket_b,receive_then_send_B_Socket; //- First Recive sockaddr_in *receive_then_send_A_Addr = new sockaddr_in; receive_then_send_A_Addr->sin_family = AF_INET; receive_then_send_A_Addr->sin_addr.s_addr = INADDR_ANY; receive_then_send_A_Addr->sin_port = htons((u_short)share_port); receive_then_send_A_Socket = socket(AF_INET, SOCK_STREAM, 0); bind(receive_then_send_A_Socket, (struct sockaddr *)receive_then_send_A_Addr, sizeof(struct sockaddr_in)); listen(receive_then_send_A_Socket, 1); receive_then_send_A_Socket_b = accept(receive_then_send_A_Socket, 0, 0); char* buffer_A= new char[100]; recv(receive_then_send_A_Socket_b, buffer_A, 100, 0); printf("[2]What I first receive: %s\n",buffer_A); //- Check receiver Port struct sockaddr_storage receiver_addr; socklen_t receiver_addr_len = (socklen_t)sizeof receiver_addr; getpeername(receive_then_send_A_Socket_b, (struct sockaddr*)&receiver_addr, &receiver_addr_len); struct sockaddr_in *s = (struct sockaddr_in *)&receiver_addr; inet_ntop(AF_INET, &s->sin_addr, share_addr, sizeof share_addr); receiver_port = ntohs(s->sin_port); printf("[2]The port I want to send to:%ld\n",receiver_port); close(receive_then_send_A_Socket); close(receive_then_send_A_Socket_b); //- Send Back to the port that sender send to me struct sockaddr_in receive_then_send_B_Addr; receive_then_send_B_Addr.sin_family = AF_INET; inet_pton(AF_INET, share_addr, &receive_then_send_B_Addr.sin_addr.s_addr); receive_then_send_B_Addr.sin_port = htons((u_short)receiver_port); receive_then_send_B_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); while (connect(receive_then_send_B_Socket, (struct sockaddr *)&receive_then_send_B_Addr, sizeof(sockaddr_in)) == SOCKET_ERROR){ printf("\nFail Code:%i\n", WSAGetLastError()); break; } send(receive_then_send_B_Socket, "1234", 5, 0); close(receive_then_send_B_Socket); printf("[2]The port I want to send to:%ld\n",receiver_port); } int main(int argc, char *argv[]) { ThreadB = std::thread(receive_then_send); ThreadA = std::thread(send_then_receive); while(1); return 0; } However, it works well in first transmission, but it doesnt work in second transmission, whats wrong???
It shows like this:
Connect Fail in first response| Fail Code:111
Connect Fail in first response| Fail Code:111 [1]The port I want to send to:8000 [1]MyPort Check:34004 [2]What I first receive: 4321 [2]The port I want to send to:34004
Fail Code:111
Note that: I use Linux (2nd transmission not work), but all functions well when i modify into WinSock version. Why this happen?
Note that Before Bind, i have tired // set SO_REUSEADDR on a socket to true (1): int optval= 1; setsockopt(receive_then_send_A_Socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));